#!/usr/bin/env node /* vim: set filetype=javascript */ var sys = require('util'); function print(){ [].slice.call(arguments).forEach(function(a){ sys.puts(a); }); } function _path(){ return [].slice.call(arguments).map(function(a){return/^(.+)\/?$/.exec(a)[1]}).join('/'); } function fh(str){ return str.replace(/[<>]/g, function(a){return a==='<'?'<':'>'}); } function findByParam(arr, name, value) { return arr.filter(function(obj){ return obj[name] === value; }); } function __extend(obj){ var args = arguments, l = args.length, i, n; for (i=1; i 1 && group.apply(this, [].slice.call(arguments, 1)); var g = builder.variables[name + 's'] = []; var sg = builder.variables['sub' + name + 's'] = []; builder.instructions.push({ name: name, exec: function(args){ args = args.split(/\s+/g); args[1] = args[1] || args[0]; builder.variables[name + 's'].push({name: args[0], assignName: args[1]}); } }, { name: 'sub' + name, exec: function(args){ args = args.split(/\s+/g); args[2] = args[2] || args[0] + args[1]; builder.variables['sub' + name + 's'].push({subOf: args[0], name: args[1], assignName: args[2], toString: Builder.Comment.prototype.toString}); } }); cp.commands.push({ name: name, exec: function(args){ args = args ? args.split(/\s+/g) : []; this.assignName = args[0]; !this.assignName && this.onfinish(function(){ this.assignName = this.name; }); this[name] = true; builder.variables[name + 's'].push(this); } }, { name: 'sub' + name, exec: function(args){ args = args ? args.split(/\s+/g) : []; this.subOf = args[0]; this.assignName = args[1]; !this.name && !this.assignName && this.onfinish(function(){ this.assignName = args[0] + this.name; }); this[name] = true; this['sub' + name] = true; builder.variables['sub' + name + 's'].push(this); } }); } group('generator', 'effect', 'control', 'processor'); cp.commands.push({ name: 'param', exec: function(args){ if (!args) return; var params = this.params = this.params || [], p = {}, s, x; while (s = /^([^\s]+)\s*/.exec(args)){ args = args.substr(s[0].length); s = s[1]; x = /^\{(.+)\}$/.exec(s); if (x) { p.type = x[1]; continue; } x = /^(.+):(.*)$/.exec(s); if (x) { p[x[1]] = x[2] || true; continue; } p.name = s; p.description = args; args = ''; break; } params.push(p); } }, { name: 'arg', exec: function(args){ if (!args) return; var arglist = this.arglist = this.arglist || [], p = {}, s, x; while (s = /^([^\s]+)\s*/.exec(args)){ args = args.substr(s[0].length); s = s[1]; x = /^\{(.+)\}$/.exec(s); if (x) { p.type = x[1]; continue; } x = /^(.+):(.*)$/.exec(s); if (x) { p[x[1]] = x[2] || true; continue; } while (/^[^\w]/.exec(s)) { switch(s[0]) { case '!': p.optional = true; break; case '=': p.assignsToClass = true; break; } s = s.substr(1); } p.name = s; p.description = args; args = ''; break; } arglist.push(p); } }, { name: 'return', exec: function(args){ if (!args) return; var p = {}, s, x, desc; while (s = /^([^\s]+)\s*/.exec(args)){ desc = args; args = args.substr(s[0].length); s = s[1]; x = /^\{(.+)\}$/.exec(s); if (x) { p.type = x[1]; continue; } p.description = desc; args = ''; break; } this.returns = p; } }, { name: 'method', exec: function(args){ args = args ? args.split(/\s+/g) : []; this.method = true; if (args[0]) { this.methodOf = args[0]; } } }, { name: 'static', exec: function(args){ args = args ? args.split(/\s+/g) : []; this.static = true; this.method = true; if (args[0]) { this.methodOf = args[0]; } } }, { name: 'class', exec: function(args){ this.class = true; } }); builder.group = group; builder.addPostProcessor(cp); builder.commentParser = cp; return builder; } if (process.argv.length < 3){ throw "Try build -h for help."; } var args = paramon.readFormat(process.argv, { name: 'build', usage: 'command [options]', params: [ { name: 'debug', args: ['--debug', '-d'], desc: 'Run in debug mode (more verbose error messages).', maxParams: 0, }, { name: 'update', args: ['update', '-u'], desc: 'Update target (wrappers).', minParams: 1, maxParams: -1, } ], }); !args.debug && process.on('uncaughtException', function(e){ print(e.toString()); process.exit(1); }); args['$!stray'].forEach(function(e){ print('Unknown build command "' + e + '".'); process.exit(); }); var updatables = { 'docs': function(){ var builder = builderContext(); builder.run(read('sink.js'), 'sink.js'); builder.commentParser.comments.forEach(function(comment){ // This is probably unnecessary payload. delete comment.body; }); var comments = builder.commentParser.comments.filter(function (func) { return func.assignName || func.class; }); builder.commentParser.comments.forEach(function(func){ if (!func.method) return; var parent = func.methodOf && findByParam(comments, 'name', func.methodOf)[0]; if (parent) { parent.methods = parent.methods || []; parent.methods.push(func); // } else { // methods.push(func); } }); var docs = '# sink.js\n\n'; comments.forEach(function (func) { docs += '## ' + (func.static ? func.methodOf + '.' : '') + (func.assignName || func.name) + '\n\n'; docs += func.text + '\n\n'; if (func.arglist) { docs += '### Arguments\n\n'; func.arglist.forEach(function(arg){ var info = arg.assignsToClass ? findByParam(func.params, 'name', arg.name)[0] || arg : arg; docs += ' * '; if (arg.optional) docs += '(Optional) '; if (info.type) docs += '(' + fh(info.type) + ') '; docs += info.name; docs += ': ' + info.description; docs += '\n'; }); docs += '\n'; } if (func.methods) { docs += '### Methods\n\n'; func.methods.forEach(function(method){ docs += '#### '; if (method.static) { docs += '(Static) '; } docs += method.name + '('; if (method.arglist) { docs += method.arglist.map(function(a){ return a.name }).join(', '); } docs += ')\n\n' + method.text + '\n\n'; if (method.arglist) { docs += '##### Arguments\n\n'; method.arglist.forEach(function(arg){ var info = arg.assignsToClass ? findByParam(func.params, 'name', arg.name)[0] || arg : arg; docs += ' * '; if (arg.optional) docs += '(Optional) '; if (info.type) docs += '(' + fh(info.type) + ') '; docs += info.name; docs += ': ' + info.description; docs += '\n'; }); docs += '\n'; } if (method.returns) { docs += '##### Returns\n\n'; if (method.returns.type) docs += '(' + fh(method.returns.type) + ') '; docs += method.returns.description; docs += '\n\n'; } }); } }); save('DOCS.md', docs); print('Documentation updated.'); }, }; if (args.update) { args.update.forEach(function(e){ e = e.toLowerCase(); var k; if (e === 'all') { for (k in updatables){ if (updatables.hasOwnProperty(k)){ updatables[k](); } } } else if (e in updatables) { updatables[e](); } else { throw 'Unknown update target "' + e + '".'; } }); process.exit(); }