first draft of options for Cakefiles, using optparse.coffee, as well as a cake install task that takes --prefix. Still need to fix the lib/bin scripts

This commit is contained in:
Jeremy Ashkenas 2010-02-25 21:43:42 -05:00
parent 55ed202957
commit 17ea48c543
5 changed files with 62 additions and 30 deletions

View File

@ -7,12 +7,16 @@ run: (args) ->
proc.addListener 'error', (err) -> if err then puts err
task 'install', 'install CoffeeScript into /usr/local', ->
option '-p', '--prefix', 'set the installation prefix for `cake install`'
task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options) ->
base: options.prefix or '/usr/local'
lib: base + '/lib/coffee-script'
exec([
'mkdir -p /usr/local/lib/coffee-script'
'cp -rf bin lib LICENSE README package.json src vendor /usr/local/lib/coffee-script'
'ln -sf /usr/local/lib/coffee-script/lib/bin/coffee /usr/local/bin/coffee'
'ln -sf /usr/local/lib/coffee-script/lib/bin/cake /usr/local/bin/cake'
'mkdir -p ' + lib
'cp -rf bin lib LICENSE README package.json src vendor ' + lib
'ln -sf ' + lib + '/lib/bin/coffee ' + base + '/bin/coffee'
'ln -sf ' + lib + '/lib/bin/cake ' + base + '/bin/cake'
].join(' && '))

View File

@ -1,5 +1,5 @@
(function(){
var coffee, fs, no_such_task, path, print_tasks, tasks;
var coffee, fs, no_such_task, oparse, options, optparse, path, print_tasks, switches, tasks;
var __hasProp = Object.prototype.hasOwnProperty;
// `cake` is a simplified version of Make (Rake, Jake) for CoffeeScript.
// You define tasks with names and descriptions in a Cakefile, and can call them
@ -7,7 +7,11 @@
fs = require('fs');
path = require('path');
coffee = require('coffee-script');
optparse = require('optparse');
tasks = {};
options = {};
switches = [];
oparse = null;
// Mixin the top-level Cake functions for Cakefiles to use.
process.mixin({
// Define a task with a name, a description, and the action itself.
@ -18,12 +22,16 @@
action: action
};
},
// Define an option that the Cakefile accepts.
option: function option(letter, flag, description) {
return switches.push([letter, flag, description]);
},
// Invoke another task in the Cakefile.
invoke: function invoke(name) {
if (!(tasks[name])) {
no_such_task(name);
}
return tasks[name].action();
return tasks[name].action(options);
}
});
// Running `cake` runs the tasks you pass asynchronously (node-style), or
@ -38,10 +46,12 @@
return fs.readFile('Cakefile', function(err, source) {
var _a, _b, _c, arg;
eval(coffee.compile(source));
oparse = new optparse.OptionParser(switches);
if (!(args.length)) {
return print_tasks();
}
_a = []; _b = args;
options = oparse.parse(args);
_a = []; _b = options.arguments;
for (_c = 0; _c < _b.length; _c++) {
arg = _b[_c];
_a.push(invoke(arg));
@ -52,23 +62,24 @@
};
// Display the list of Cake tasks.
print_tasks = function print_tasks() {
var _a, _b, _c, _d, _e, _f, _g, i, name, spaces, task;
_a = []; _b = tasks;
for (name in _b) { if (__hasProp.call(_b, name)) {
task = _b[name];
_a.push((function() {
spaces = 20 - name.length;
spaces = spaces > 0 ? (function() {
_c = []; _f = 0; _g = spaces;
for (_e = 0, i=_f; (_f <= _g ? i <= _g : i >= _g); (_f <= _g ? i += 1 : i -= 1), _e++) {
_c.push(' ');
}
return _c;
}).call(this).join('') : '';
return puts("cake " + name + spaces + ' # ' + task.description);
}).call(this));
var _a, _b, _c, _d, _e, _f, i, name, spaces, task;
puts('');
_a = tasks;
for (name in _a) { if (__hasProp.call(_a, name)) {
task = _a[name];
spaces = 20 - name.length;
spaces = spaces > 0 ? (function() {
_b = []; _e = 0; _f = spaces;
for (_d = 0, i=_e; (_e <= _f ? i <= _f : i >= _f); (_e <= _f ? i += 1 : i -= 1), _d++) {
_b.push(' ');
}
return _b;
}).call(this).join('') : '';
puts("cake " + name + spaces + ' # ' + task.description);
}}
return _a;
if (switches.length) {
return puts('\n' + oparse.help() + '\n');
}
};
// Print an error and exit when attempting to all an undefined task.
no_such_task = function no_such_task(task) {

View File

@ -4,7 +4,7 @@
// [short-flag (optional), long-flag, description]
// And an optional banner for the usage help.
op = (exports.OptionParser = function OptionParser(rules, banner) {
this.banner = banner || 'Usage: [Options]';
this.banner = banner;
this.rules = build_rules(rules);
return this;
});
@ -42,7 +42,10 @@
// Return the help text for this OptionParser, for --help and such.
op.prototype.help = function help() {
var _a, _b, _c, _d, _e, _f, _g, i, let_part, lines, rule, spaces;
lines = [this.banner, '', 'Available options:'];
lines = ['Available options:'];
if (this.banner) {
lines.unshift(this.banner + '\n');
}
_a = this.rules;
for (_b = 0; _b < _a.length; _b++) {
rule = _a[_b];

View File

@ -5,8 +5,12 @@
fs: require 'fs'
path: require 'path'
coffee: require 'coffee-script'
optparse: require 'optparse'
tasks: {}
options: {}
switches: []
oparse: null
# Mixin the top-level Cake functions for Cakefiles to use.
process.mixin {
@ -15,10 +19,15 @@ process.mixin {
task: (name, description, action) ->
tasks[name]: {name: name, description: description, action: action}
# Define an option that the Cakefile accepts.
option: (letter, flag, description) ->
switches.push [letter, flag, description]
# Invoke another task in the Cakefile.
invoke: (name) ->
no_such_task name unless tasks[name]
tasks[name].action()
tasks[name].action(options)
}
# Running `cake` runs the tasks you pass asynchronously (node-style), or
@ -29,15 +38,19 @@ exports.run: ->
args: process.ARGV[2...process.ARGV.length]
fs.readFile 'Cakefile', (err, source) ->
eval coffee.compile source
oparse: new optparse.OptionParser switches
return print_tasks() unless args.length
invoke arg for arg in args
options: oparse.parse(args)
invoke arg for arg in options.arguments
# Display the list of Cake tasks.
print_tasks: ->
puts ''
for name, task of tasks
spaces: 20 - name.length
spaces: if spaces > 0 then (' ' for i in [0..spaces]).join('') else ''
puts "cake " + name + spaces + ' # ' + task.description
puts '\n' + oparse.help() + '\n' if switches.length
# Print an error and exit when attempting to all an undefined task.
no_such_task: (task) ->

View File

@ -2,7 +2,7 @@
# [short-flag (optional), long-flag, description]
# And an optional banner for the usage help.
op: exports.OptionParser: (rules, banner) ->
@banner: banner or 'Usage: [Options]'
@banner: banner
@rules: build_rules(rules)
this
@ -26,7 +26,8 @@ op::parse: (args) ->
# Return the help text for this OptionParser, for --help and such.
op::help: ->
lines: [@banner, '', 'Available options:']
lines: ['Available options:']
lines.unshift @banner + '\n' if @banner
for rule in @rules
spaces: 15 - rule.flag.length
spaces: if spaces > 0 then (' ' for i in [0..spaces]).join('') else ''