sproutit-narwhal 0.1.106
Sign up to get free protection for your applications and to get access to all the features.
- data/DISTRIBUTION.yml +15 -0
- data/README.md +86 -0
- data/Rakefile +349 -0
- data/VERSION.yml +7 -0
- data/bin/activate +50 -0
- data/bin/activate.bash +50 -0
- data/bin/activate.cmd +3 -0
- data/bin/js +67 -0
- data/bin/json +2 -0
- data/bin/narwhal +67 -0
- data/bin/narwhal.cmd +29 -0
- data/bin/sea +45 -0
- data/bin/sea.cmd +25 -0
- data/bin/tusk +2 -0
- data/bin/tusk.cmd +5 -0
- data/catalog.json +902 -0
- data/docs/available-packages.md +32 -0
- data/docs/browser-api-plan.md +290 -0
- data/docs/browser-api.md +153 -0
- data/docs/download.md +25 -0
- data/docs/engines.md +32 -0
- data/docs/json-tool.md +121 -0
- data/docs/lib/binary.wiki +242 -0
- data/docs/lib/file.wiki +325 -0
- data/docs/lib/os/popen.md +70 -0
- data/docs/modules.md +38 -0
- data/docs/narwhal.md +487 -0
- data/docs/packages-howto.md +32 -0
- data/docs/packages.md +30 -0
- data/docs/posts/2009-07-29-hello-0.1.md +19 -0
- data/docs/quick-start.md +69 -0
- data/docs/sea.md +49 -0
- data/engines/browser/lib/binary.js +2 -0
- data/engines/browser/lib/reactor.js +21 -0
- data/engines/browser/lib/system.js +3 -0
- data/engines/default/lib/array.js +164 -0
- data/engines/default/lib/binary-engine.js +53 -0
- data/engines/default/lib/binary.js +755 -0
- data/engines/default/lib/date.js +8 -0
- data/engines/default/lib/file-engine.js +119 -0
- data/engines/default/lib/function.js +119 -0
- data/engines/default/lib/global.js +11 -0
- data/engines/default/lib/io-engine.js +26 -0
- data/engines/default/lib/json.js +488 -0
- data/engines/default/lib/object.js +69 -0
- data/engines/default/lib/os-engine.js +3 -0
- data/engines/default/lib/reactor.js +12 -0
- data/engines/default/lib/string.js +84 -0
- data/engines/default/lib/system.js +20 -0
- data/engines/default/lib/worker.js +133 -0
- data/engines/jsc/README.md +18 -0
- data/engines/jsc/bootstrap.js +53 -0
- data/engines/jsc/deps/http-parser/LICENSE +77 -0
- data/engines/jsc/deps/http-parser/README.md +145 -0
- data/engines/jsc/deps/http-parser/http_parser.c +6087 -0
- data/engines/jsc/deps/http-parser/http_parser.h +141 -0
- data/engines/jsc/deps/http-parser/http_parser.rl +500 -0
- data/engines/jsc/deps/http-parser/test.c +858 -0
- data/engines/jsc/include/binary-engine.h +11 -0
- data/engines/jsc/include/io-engine.h +23 -0
- data/engines/jsc/include/narwhal.h +427 -0
- data/engines/jsc/lib/file-engine.js +31 -0
- data/engines/jsc/lib/http.js +1 -0
- data/engines/jsc/lib/io-engine.js +202 -0
- data/engines/jsc/lib/os-engine.js +25 -0
- data/engines/jsc/lib/system.js +18 -0
- data/engines/jsc/lib/zip.js +1 -0
- data/engines/jsc/narwhal-jsc.c +273 -0
- data/engines/jsc/narwhal.c +29 -0
- data/engines/jsc/package.json +8 -0
- data/engines/jsc/src/binary-engine.cc +290 -0
- data/engines/jsc/src/file-engine.cc +405 -0
- data/engines/jsc/src/io-engine.cc +423 -0
- data/engines/jsc/src/jack/handler/jill.cc +710 -0
- data/engines/jsc/src/os-engine.cc +210 -0
- data/engines/rhino/bin/narwhal-rhino +68 -0
- data/engines/rhino/bin/narwhal-rhino.cmd +34 -0
- data/engines/rhino/bootstrap.js +119 -0
- data/engines/rhino/jars/jline.jar +0 -0
- data/engines/rhino/jars/jna.jar +0 -0
- data/engines/rhino/jars/js.jar +0 -0
- data/engines/rhino/lib/binary-engine.js +83 -0
- data/engines/rhino/lib/concurrency.js +6 -0
- data/engines/rhino/lib/event-queue.js +18 -0
- data/engines/rhino/lib/file-engine.js +216 -0
- data/engines/rhino/lib/http-client-engine.js +90 -0
- data/engines/rhino/lib/http-engine.js +10 -0
- data/engines/rhino/lib/io-engine.js +347 -0
- data/engines/rhino/lib/md5-engine.js +40 -0
- data/engines/rhino/lib/os-engine.js +150 -0
- data/engines/rhino/lib/packages-engine.js +71 -0
- data/engines/rhino/lib/sandbox-engine.js +70 -0
- data/engines/rhino/lib/system.js +38 -0
- data/engines/rhino/lib/worker-engine.js +23 -0
- data/engines/rhino/lib/zip.js +78 -0
- data/engines/rhino/package.json +4 -0
- data/engines/secure/lib/file.js +6 -0
- data/engines/secure/lib/system.js +6 -0
- data/engines/template/bin/narwhal-engine-name +32 -0
- data/engines/template/bootstrap.js +40 -0
- data/engines/template/lib/file-engine.js +118 -0
- data/engines/template/lib/system.js +17 -0
- data/examples/browser-deployment-jackconfig.js +35 -0
- data/examples/fibonacci-worker.js +35 -0
- data/examples/fibonacci.js +19 -0
- data/examples/hello +2 -0
- data/examples/narwhal +3 -0
- data/examples/not-quite-a-quine.js +1 -0
- data/extconf.rb +44 -0
- data/gem_bin/narwhal +5 -0
- data/gem_bin/sea +4 -0
- data/gem_bin/tusk +4 -0
- data/lib/args.js +849 -0
- data/lib/base16.js +16 -0
- data/lib/base64.js +120 -0
- data/lib/codec/base64.js +8 -0
- data/lib/crc32.js +60 -0
- data/lib/file-bootstrap.js +187 -0
- data/lib/file.js +659 -0
- data/lib/hash.js +28 -0
- data/lib/hashp.js +65 -0
- data/lib/html.js +16 -0
- data/lib/http-client.js +134 -0
- data/lib/http.js +17 -0
- data/lib/io.js +98 -0
- data/lib/jsmin.js +315 -0
- data/lib/jsonpath.js +89 -0
- data/lib/logger.js +55 -0
- data/lib/md4.js +146 -0
- data/lib/md5.js +164 -0
- data/lib/mime.js +166 -0
- data/lib/narwhal.js +102 -0
- data/lib/narwhal/client.js +261 -0
- data/lib/narwhal/compile.js +99 -0
- data/lib/narwhal/env.js +140 -0
- data/lib/narwhal/inline.js +106 -0
- data/lib/narwhal/json.js +324 -0
- data/lib/narwhal/json.md +178 -0
- data/lib/narwhal/repl.js +96 -0
- data/lib/narwhal/server-test.js +6 -0
- data/lib/narwhal/server.js +270 -0
- data/lib/narwhal/tusk.js +170 -0
- data/lib/narwhal/tusk/bin.js +13 -0
- data/lib/narwhal/tusk/bundle.js +0 -0
- data/lib/narwhal/tusk/catalog.js +22 -0
- data/lib/narwhal/tusk/clone.js +66 -0
- data/lib/narwhal/tusk/consolidate.js +25 -0
- data/lib/narwhal/tusk/create-catalog.js +80 -0
- data/lib/narwhal/tusk/engine.js +42 -0
- data/lib/narwhal/tusk/freeze.js +0 -0
- data/lib/narwhal/tusk/init.js +56 -0
- data/lib/narwhal/tusk/install.js +288 -0
- data/lib/narwhal/tusk/list.js +20 -0
- data/lib/narwhal/tusk/orphans.js +0 -0
- data/lib/narwhal/tusk/reheat.js +15 -0
- data/lib/narwhal/tusk/remove.js +15 -0
- data/lib/narwhal/tusk/search.js +145 -0
- data/lib/narwhal/tusk/update.js +21 -0
- data/lib/narwhal/tusk/upgrade.js +0 -0
- data/lib/os.js +33 -0
- data/lib/packages.js +423 -0
- data/lib/printf.js +169 -0
- data/lib/promise.js +352 -0
- data/lib/querystring.js +176 -0
- data/lib/ref-send.js +257 -0
- data/lib/regexp.js +12 -0
- data/lib/sandbox.js +422 -0
- data/lib/sha.js +112 -0
- data/lib/sha256.js +102 -0
- data/lib/struct.js +228 -0
- data/lib/term.js +179 -0
- data/lib/test/assert.js +95 -0
- data/lib/test/equiv.js +188 -0
- data/lib/test/jsdump.js +165 -0
- data/lib/test/runner.js +129 -0
- data/lib/unload.js +13 -0
- data/lib/uri.js +378 -0
- data/lib/url.js +5 -0
- data/lib/utf8.js +64 -0
- data/lib/util.js +985 -0
- data/lib/uuid.js +89 -0
- data/lib/xregexp.js +521 -0
- data/local.json.template +1 -0
- data/narwhal.gemspec +105 -0
- data/narwhal.js +213 -0
- data/package.json +26 -0
- data/packages/readline/engines/default/lib/readline.js +4 -0
- data/packages/readline/engines/rhino/lib/readline.js +6 -0
- data/packages/readline/package.json +5 -0
- data/sources.json +207 -0
- data/tests/all-tests.js +17 -0
- data/tests/args.js +31 -0
- data/tests/args/domain.js +215 -0
- data/tests/args/options.js +36 -0
- data/tests/args/shifting.js +92 -0
- data/tests/args/validation.js +31 -0
- data/tests/base64.js +23 -0
- data/tests/commonjs.js +3 -0
- data/tests/commonjs/all-tests.js +12 -0
- data/tests/commonjs/bytearray-encodings-tests.js +69 -0
- data/tests/commonjs/bytearray-tests.js +465 -0
- data/tests/commonjs/bytestring-encodings-tests.js +89 -0
- data/tests/commonjs/bytestring-tests.js +263 -0
- data/tests/commonjs/es5/all-tests.js +3 -0
- data/tests/commonjs/es5/bind.js +29 -0
- data/tests/commonjs/file-tests.js +315 -0
- data/tests/commonjs/file/dirname.js +31 -0
- data/tests/commonjs/file/extension.js +45 -0
- data/tests/commonjs/file/is-absolute.js +11 -0
- data/tests/commonjs/file/iterator.js +101 -0
- data/tests/commonjs/file/normal.js +27 -0
- data/tests/commonjs/file/path.js +17 -0
- data/tests/commonjs/file/relative.js +42 -0
- data/tests/commonjs/file/resolve.js +44 -0
- data/tests/commonjs/module-tests.js +9 -0
- data/tests/commonjs/modules/absolute/b.js +1 -0
- data/tests/commonjs/modules/absolute/program.js +5 -0
- data/tests/commonjs/modules/absolute/submodule/a.js +3 -0
- data/tests/commonjs/modules/absolute/test.js +9 -0
- data/tests/commonjs/modules/all-tests.js +47 -0
- data/tests/commonjs/modules/config.js +11 -0
- data/tests/commonjs/modules/cyclic/a.js +4 -0
- data/tests/commonjs/modules/cyclic/b.js +4 -0
- data/tests/commonjs/modules/cyclic/program.js +10 -0
- data/tests/commonjs/modules/cyclic/test.js +9 -0
- data/tests/commonjs/modules/determinism/program.js +3 -0
- data/tests/commonjs/modules/determinism/submodule/a.js +8 -0
- data/tests/commonjs/modules/determinism/submodule/b.js +2 -0
- data/tests/commonjs/modules/determinism/test.js +9 -0
- data/tests/commonjs/modules/exactExports/a.js +3 -0
- data/tests/commonjs/modules/exactExports/program.js +4 -0
- data/tests/commonjs/modules/exactExports/test.js +9 -0
- data/tests/commonjs/modules/hasOwnProperty/hasOwnProperty.js +0 -0
- data/tests/commonjs/modules/hasOwnProperty/program.js +3 -0
- data/tests/commonjs/modules/hasOwnProperty/test.js +9 -0
- data/tests/commonjs/modules/hasOwnProperty/toString.js +0 -0
- data/tests/commonjs/modules/method/a.js +12 -0
- data/tests/commonjs/modules/method/program.js +8 -0
- data/tests/commonjs/modules/method/test.js +9 -0
- data/tests/commonjs/modules/missing/program.js +8 -0
- data/tests/commonjs/modules/missing/test.js +9 -0
- data/tests/commonjs/modules/monkeys/a.js +1 -0
- data/tests/commonjs/modules/monkeys/program.js +4 -0
- data/tests/commonjs/modules/monkeys/test.js +9 -0
- data/tests/commonjs/modules/nested/a/b/c/d.js +3 -0
- data/tests/commonjs/modules/nested/program.js +3 -0
- data/tests/commonjs/modules/nested/test.js +9 -0
- data/tests/commonjs/modules/relative/program.js +5 -0
- data/tests/commonjs/modules/relative/submodule/a.js +1 -0
- data/tests/commonjs/modules/relative/submodule/b.js +2 -0
- data/tests/commonjs/modules/relative/test.js +9 -0
- data/tests/commonjs/modules/transitive/a.js +1 -0
- data/tests/commonjs/modules/transitive/b.js +1 -0
- data/tests/commonjs/modules/transitive/c.js +3 -0
- data/tests/commonjs/modules/transitive/program.js +3 -0
- data/tests/commonjs/modules/transitive/test.js +9 -0
- data/tests/file/all-tests.js +61 -0
- data/tests/file/fnmatch.js +102 -0
- data/tests/file/glob.js +466 -0
- data/tests/file/match.js +102 -0
- data/tests/global.js +6 -0
- data/tests/global/array.js +19 -0
- data/tests/hashes.js +94 -0
- data/tests/html.js +13 -0
- data/tests/io/stringio.js +21 -0
- data/tests/os/all-tests.js +4 -0
- data/tests/os/popen.js +41 -0
- data/tests/os/system.js +22 -0
- data/tests/printf.js +123 -0
- data/tests/query-string.js +87 -0
- data/tests/sandbox/byte-io.js +20 -0
- data/tests/sandbox/fileName.js +3 -0
- data/tests/sandbox/foo.js +0 -0
- data/tests/sandbox/reload.js +79 -0
- data/tests/string.js +35 -0
- data/tests/uri.js +41 -0
- data/tests/util/all-tests.js +79 -0
- data/tests/util/array.js +207 -0
- data/tests/util/array/is-arguments.js +29 -0
- data/tests/util/array/is-array-like.js +29 -0
- data/tests/util/case.js +9 -0
- data/tests/util/collection.js +104 -0
- data/tests/util/eq.js +57 -0
- data/tests/util/expand.js +45 -0
- data/tests/util/object.js +125 -0
- data/tests/util/operator.js +25 -0
- data/tests/util/range.js +19 -0
- data/tests/util/repr.js +26 -0
- data/tests/util/string.js +34 -0
- data/tests/util/unique.js +12 -0
- metadata +434 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# get the absolute path of the executable
|
4
|
+
SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0")
|
5
|
+
|
6
|
+
# resolve symlinks
|
7
|
+
while [ -h "$SELF_PATH" ]; do
|
8
|
+
DIR=$(dirname -- "$SELF_PATH")
|
9
|
+
SYM=$(readlink -- "$SELF_PATH")
|
10
|
+
SELF_PATH=$(cd -- "$DIR" && cd -- $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
|
11
|
+
done
|
12
|
+
|
13
|
+
NARWHAL_ENGINE_HOME=$(dirname -- $(dirname -- $SELF_PATH))
|
14
|
+
BOOTSTRAP="$NARWHAL_ENGINE_HOME/bootstrap.js"
|
15
|
+
|
16
|
+
if [ ! "$NARWHAL_HOME" ]; then
|
17
|
+
NARWHAL_HOME=$(dirname -- $(dirname -- $NARWHAL_ENGINE_HOME))
|
18
|
+
fi
|
19
|
+
|
20
|
+
export NARWHAL_HOME
|
21
|
+
|
22
|
+
# uses rlwrap (readline wrapper) if present
|
23
|
+
NARWHAL="$(which rlwrap) narwhal-engine" # TODO replace narwhal-engine with js bin
|
24
|
+
|
25
|
+
# drop into shell if there are no additional arguments
|
26
|
+
if [ $# -lt 1 ]; then
|
27
|
+
# FIXME: no way to explicitly drop into shell
|
28
|
+
$NARWHAL $BOOTSTRAP "$@"
|
29
|
+
else
|
30
|
+
MAIN=$(cd -P -- "$(dirname -- "$1")" && pwd -P) && MAIN=$MAIN/$(basename -- "$1" .js)
|
31
|
+
$NARWHAL $BOOTSTRAP $MAIN "$0" "$@"
|
32
|
+
fi
|
@@ -0,0 +1,40 @@
|
|
1
|
+
(function (evalGlobal) {
|
2
|
+
|
3
|
+
var read = /*TODO*/; // function(path:string):string
|
4
|
+
|
5
|
+
var isFile = /*TODO*/; // function(path:string):boolean
|
6
|
+
|
7
|
+
var prefix = "/path/to/narwhal"; /*TODO*/
|
8
|
+
var enginePrefix = "/path/to/engine"; /*TODO*/
|
9
|
+
|
10
|
+
eval(read(prefix + "/narwhal.js"))({
|
11
|
+
global: this,
|
12
|
+
evalGlobal: evalGlobal,
|
13
|
+
engine: '<<<name>>>', /*TODO*/
|
14
|
+
engines: ['<<<name>>>', 'default'], /*TODO*/
|
15
|
+
os: "", /* TODO /\bwindows\b/i for Windows FS support */
|
16
|
+
// XXX engines may include any number of
|
17
|
+
// prioritized generic engines like:
|
18
|
+
// rhino, java, c, v8, default
|
19
|
+
print: print,
|
20
|
+
evaluate: function (text) {
|
21
|
+
// TODO maybe something better here:
|
22
|
+
return eval(
|
23
|
+
"(function(require,exports,module,system,print){" +
|
24
|
+
text +
|
25
|
+
"/**/\n})"
|
26
|
+
);
|
27
|
+
},
|
28
|
+
fs: {
|
29
|
+
read: read,
|
30
|
+
isFile: isFile
|
31
|
+
},
|
32
|
+
prefix: prefix,
|
33
|
+
prefixes: [prefix, enginePrefix],
|
34
|
+
debug: false,
|
35
|
+
verbose: false
|
36
|
+
});
|
37
|
+
|
38
|
+
}).call(this, function () {
|
39
|
+
return eval(arguments[0]);
|
40
|
+
});
|
@@ -0,0 +1,118 @@
|
|
1
|
+
|
2
|
+
var exports = require('./file');
|
3
|
+
|
4
|
+
exports.SEPARATOR = '/';
|
5
|
+
|
6
|
+
exports.cwd = function () {
|
7
|
+
throw Error("cwd not yet implemented.");
|
8
|
+
};
|
9
|
+
|
10
|
+
// TODO necessary for package loading
|
11
|
+
exports.list = function (path) {
|
12
|
+
throw Error("list not yet implemented.");
|
13
|
+
};
|
14
|
+
|
15
|
+
// TODO necessary for package loading
|
16
|
+
exports.canonical = function (path) {
|
17
|
+
throw Error("canonical not yet implemented.");
|
18
|
+
};
|
19
|
+
|
20
|
+
exports.exists = function (path) {
|
21
|
+
throw Error("exists not yet implemented.");
|
22
|
+
};
|
23
|
+
|
24
|
+
// TODO necessary for lazy module reloading in sandboxes
|
25
|
+
exports.mtime = function (path) {
|
26
|
+
throw Error("mtime not yet implemented.");
|
27
|
+
};
|
28
|
+
|
29
|
+
exports.size = function (path) {
|
30
|
+
throw Error("size not yet implemented.");
|
31
|
+
};
|
32
|
+
|
33
|
+
exports.stat = function (path) {
|
34
|
+
return {
|
35
|
+
mtime: exports.mtime(path),
|
36
|
+
size: exports.size(path)
|
37
|
+
}
|
38
|
+
};
|
39
|
+
|
40
|
+
// TODO necessary for package loading
|
41
|
+
exports.isDirectory = function (path) {
|
42
|
+
throw Error("isDirectory not yet implemented.");
|
43
|
+
};
|
44
|
+
|
45
|
+
// TODO necessary for module loading
|
46
|
+
exports.isFile = function (path) {
|
47
|
+
throw Error("isFile not yet implemented.");
|
48
|
+
};
|
49
|
+
// XXX remove this if you implement isFile here
|
50
|
+
// from bootstrap system object:
|
51
|
+
exports.isFile = system.fs.isFile;
|
52
|
+
|
53
|
+
exports.isFile = system.fs.isFile; // TEMPORARY HACK
|
54
|
+
|
55
|
+
exports.isLink = function (path) {
|
56
|
+
throw Error("isLink not yet implemented.");
|
57
|
+
};
|
58
|
+
|
59
|
+
exports.isReadable = function (path) {
|
60
|
+
throw Error("isReadable not yet implemented.");
|
61
|
+
};
|
62
|
+
|
63
|
+
exports.isWritable = function (path) {
|
64
|
+
throw Error("isWritable not yet implemented.");
|
65
|
+
};
|
66
|
+
|
67
|
+
exports.rename = function (source, target) {
|
68
|
+
throw Error("rename not yet implemented.");
|
69
|
+
};
|
70
|
+
|
71
|
+
exports.move = function (source, target) {
|
72
|
+
throw Error("move not yet implemented.");
|
73
|
+
};
|
74
|
+
|
75
|
+
exports.remove = function (path) {
|
76
|
+
throw Error("remove not yet implemented.");
|
77
|
+
};
|
78
|
+
|
79
|
+
exports.mkdir = function (path) {
|
80
|
+
throw Error("mkdir not yet implemented.");
|
81
|
+
};
|
82
|
+
|
83
|
+
exports.rmdir = function(path) {
|
84
|
+
throw Error("rmdir not yet implemented.");
|
85
|
+
};
|
86
|
+
|
87
|
+
exports.touch = function (path, mtime) {
|
88
|
+
throw Error("touch not yet implemented.");
|
89
|
+
};
|
90
|
+
|
91
|
+
// FIXME temporary hack
|
92
|
+
var read = system.fs.read; // from bootstrap system object
|
93
|
+
|
94
|
+
exports.FileIO = function (path, mode, permissions) {
|
95
|
+
mode = exports.mode(mode);
|
96
|
+
var read = mode.read,
|
97
|
+
write = mode.write,
|
98
|
+
append = mode.append,
|
99
|
+
update = mode.update;
|
100
|
+
|
101
|
+
if (update) {
|
102
|
+
throw new Error("Updating IO not yet implemented.");
|
103
|
+
} else if (write || append) {
|
104
|
+
throw new Error("Writing IO not yet implemented.");
|
105
|
+
} else if (read) {
|
106
|
+
// FIXME temporary hack
|
107
|
+
return {
|
108
|
+
'read': function () {
|
109
|
+
return read(path);
|
110
|
+
},
|
111
|
+
'close': function () {
|
112
|
+
}
|
113
|
+
};
|
114
|
+
} else {
|
115
|
+
throw new Error("Files must be opened either for read, write, or update mode.");
|
116
|
+
}
|
117
|
+
};
|
118
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
var IO = require("./io").IO;
|
3
|
+
|
4
|
+
exports.stdin = /*TODO*/
|
5
|
+
exports.stdout = /*TODO*/
|
6
|
+
exports.stderr = /*TODO*/
|
7
|
+
|
8
|
+
exports.args = [/*TODO*/];
|
9
|
+
|
10
|
+
exports.env = {}; /*TODO*/
|
11
|
+
|
12
|
+
exports.fs = require('./file');
|
13
|
+
|
14
|
+
// default logger
|
15
|
+
var Logger = require("./logger").Logger;
|
16
|
+
exports.log = new Logger(exports.stdout);
|
17
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
var jackutil = require("jack/utils");
|
3
|
+
|
4
|
+
var app = function (env) {
|
5
|
+
if (/^../.test(env.PATH_INFO))
|
6
|
+
return jackutil.responseForStatus(404, env.PATH_INFO);
|
7
|
+
return {
|
8
|
+
"status": 200,
|
9
|
+
"headers": {"Content-type": "text/html"},
|
10
|
+
"body": [
|
11
|
+
"<html><head><script>" +
|
12
|
+
|
13
|
+
// 1.) preload transitive dependencies and
|
14
|
+
// then require.
|
15
|
+
env.script.require("narwhal/server-test") +
|
16
|
+
|
17
|
+
// 2.) embed with transitive dependencies
|
18
|
+
//env.script.embed("narwhal/server-test") +
|
19
|
+
|
20
|
+
// 3.) no preloading, all async
|
21
|
+
//env.script.loader("narwhal/server-test") +
|
22
|
+
//".async('narwhal/server-test');" +
|
23
|
+
|
24
|
+
"</script></head><body></body></html>"
|
25
|
+
]
|
26
|
+
};
|
27
|
+
};
|
28
|
+
app = require("narwhal/server").App(app, {
|
29
|
+
"debug": true // turn off debug for minification
|
30
|
+
//"path": "javascript/", // to use an alternate path to the module tree
|
31
|
+
//"proxy": "http://example.com/.js/", // to use a caching proxy
|
32
|
+
});
|
33
|
+
app = require("jack").ContentLength(app);
|
34
|
+
exports.app = app;
|
35
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
// Adapted from https://developer.mozilla.org/En/Using_web_workers
|
2
|
+
|
3
|
+
var Worker = require("worker").Worker;
|
4
|
+
|
5
|
+
var results = [];
|
6
|
+
|
7
|
+
function resultReceiver(event) {
|
8
|
+
results.push(parseInt(event.data));
|
9
|
+
if (results.length == 2) {
|
10
|
+
postMessage(results[0] + results[1]);
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
function errorReceiver(event) {
|
15
|
+
throw event.data;
|
16
|
+
}
|
17
|
+
|
18
|
+
onmessage = function(event) {
|
19
|
+
var n = parseInt(event.data);
|
20
|
+
|
21
|
+
if (n == 0 || n == 1) {
|
22
|
+
postMessage(n);
|
23
|
+
return;
|
24
|
+
}
|
25
|
+
|
26
|
+
for (var i = 1; i <= 2; i++) {
|
27
|
+
var worker = new Worker(module.path);
|
28
|
+
worker.onmessage = resultReceiver;
|
29
|
+
worker.onerror = errorReceiver;
|
30
|
+
worker.postMessage(n - i);
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
34
|
+
if (module.id == require.main)
|
35
|
+
print("Run fibonacci.js instead of fibonacci-worker.js");
|
@@ -0,0 +1,19 @@
|
|
1
|
+
// Adapted from https://developer.mozilla.org/En/Using_web_workers
|
2
|
+
|
3
|
+
var FILE = require("file"),
|
4
|
+
Worker = require("worker").Worker;
|
5
|
+
|
6
|
+
var worker = new Worker(FILE.join(FILE.dirname(module.path), "fibonacci-worker.js"));
|
7
|
+
|
8
|
+
worker.onmessage = function(event) {
|
9
|
+
print("Got: " + event.data);
|
10
|
+
}
|
11
|
+
|
12
|
+
worker.onerror = function(error) {
|
13
|
+
print("Worker error: " + error.message);
|
14
|
+
}
|
15
|
+
|
16
|
+
worker.postMessage(5);
|
17
|
+
|
18
|
+
// event loop
|
19
|
+
while(true) require("event-queue").nextEvent()();
|
data/examples/hello
ADDED
data/examples/narwhal
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
system.stdout.write(system.fs.read(module.path)).flush();
|
data/extconf.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
# Choose the best default engine for this platform and make it if needed.
|
5
|
+
|
6
|
+
NARWHAL_ROOT = File.expand_path(File.dirname(__FILE__))
|
7
|
+
CONF_PATH = File.join(NARWHAL_ROOT, 'narwhal.conf')
|
8
|
+
MAKEFILE = File.join(NARWHAL_ROOT, 'Makefile')
|
9
|
+
|
10
|
+
TEST_PATH = File.join("", "System", "Library", "Frameworks", "JavaScriptCore.framework")
|
11
|
+
JSC_ENGINE = File.join(NARWHAL_ROOT, 'engines', 'jsc')
|
12
|
+
|
13
|
+
# Detect JSC
|
14
|
+
if File.exists?(TEST_PATH) && File.exists?(JSC_ENGINE)
|
15
|
+
puts "Using JavaScript Core Engine"
|
16
|
+
|
17
|
+
fp = File.open(CONF_PATH, 'w+')
|
18
|
+
fp.write %(NARWHAL_ENGINE="jsc"\n)
|
19
|
+
fp.write %(NARWHAL_ENGINE_HOME="engines/jsc"\n)
|
20
|
+
fp.close
|
21
|
+
|
22
|
+
fp = File.open(MAKEFILE, 'w+')
|
23
|
+
fp.write %(default:\n)
|
24
|
+
fp.write %(\tcd #{JSC_ENGINE}; make\n)
|
25
|
+
fp.write %(\n)
|
26
|
+
|
27
|
+
fp.write %(install:\n)
|
28
|
+
fp.write %(\t# do nothing\n)
|
29
|
+
fp.close
|
30
|
+
|
31
|
+
# Fallback
|
32
|
+
else
|
33
|
+
puts "Using Default Rhino Engine"
|
34
|
+
fp = File.open(MAKEFILE, 'w+')
|
35
|
+
fp.write %(default:\n)
|
36
|
+
fp.write %(\n)
|
37
|
+
fp.write %(install:\n)
|
38
|
+
fp.write %(\n)
|
39
|
+
fp.close
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
data/gem_bin/narwhal
ADDED
data/gem_bin/sea
ADDED
data/gem_bin/tusk
ADDED
data/lib/args.js
ADDED
@@ -0,0 +1,849 @@
|
|
1
|
+
|
2
|
+
var os = require('os');
|
3
|
+
var util = require('util');
|
4
|
+
var stream = require('term').stream;
|
5
|
+
var system = require('system');
|
6
|
+
|
7
|
+
exports.UsageError = function (message) {
|
8
|
+
this.name = "UsageError";
|
9
|
+
this.message = message;
|
10
|
+
};
|
11
|
+
|
12
|
+
exports.UsageError.prototype = Object.create(Error.prototype);
|
13
|
+
|
14
|
+
exports.ConfigurationError = function (message) {
|
15
|
+
this.name = "ConfigurationError";
|
16
|
+
this.message = message;
|
17
|
+
};
|
18
|
+
|
19
|
+
exports.ConfigurationError.prototype = Object.create(Error.prototype);
|
20
|
+
|
21
|
+
exports.Parser = function () {
|
22
|
+
this._options = [];
|
23
|
+
this._def = {};
|
24
|
+
this._long = {};
|
25
|
+
this._short = {};
|
26
|
+
this._commands = {};
|
27
|
+
this._args = [];
|
28
|
+
this._vargs = undefined;
|
29
|
+
};
|
30
|
+
|
31
|
+
exports.Parser.prototype.option = function () {
|
32
|
+
var option = new this.Option(this, arguments);
|
33
|
+
this._options.push(option);
|
34
|
+
return option;
|
35
|
+
};
|
36
|
+
|
37
|
+
exports.Parser.prototype.group = function (name) {
|
38
|
+
var group = new this.Group(this, this, name);
|
39
|
+
this._options.push(group);
|
40
|
+
return group;
|
41
|
+
};
|
42
|
+
|
43
|
+
exports.Parser.prototype.def = function (name, value) {
|
44
|
+
this._def[name] = value;
|
45
|
+
return this;
|
46
|
+
};
|
47
|
+
|
48
|
+
exports.Parser.prototype.reset = function (options) {
|
49
|
+
for (var name in this._def) {
|
50
|
+
if (util.has(this._def, name))
|
51
|
+
options[name] = util.copy(this._def[name]);
|
52
|
+
}
|
53
|
+
this._options.forEach(function (option) {
|
54
|
+
options[option.getName()] = option._def;
|
55
|
+
});
|
56
|
+
};
|
57
|
+
|
58
|
+
exports.Parser.prototype.command = function (name, handler) {
|
59
|
+
var parent = this;
|
60
|
+
if (!handler) {
|
61
|
+
var parser = new exports.Parser();
|
62
|
+
this._commands[name] = function () {
|
63
|
+
return parser;
|
64
|
+
};
|
65
|
+
return parser;
|
66
|
+
} else if (typeof handler == "string") {
|
67
|
+
this._commands[name] = function () {
|
68
|
+
return require(handler).parser;
|
69
|
+
};
|
70
|
+
return;
|
71
|
+
} else {
|
72
|
+
var parser = new this.Parser();
|
73
|
+
parser.action(handler);
|
74
|
+
this._commands[name] = function () {
|
75
|
+
return parser;
|
76
|
+
};
|
77
|
+
return parser;
|
78
|
+
}
|
79
|
+
};
|
80
|
+
|
81
|
+
exports.Parser.prototype.arg = function (name) {
|
82
|
+
var argument = new exports.Argument(this).name(name);
|
83
|
+
this._args.push(argument);
|
84
|
+
return argument;
|
85
|
+
};
|
86
|
+
|
87
|
+
exports.Parser.prototype.args = function (name) {
|
88
|
+
var argument = new exports.Argument(this).name(name);
|
89
|
+
this._vargs = argument;
|
90
|
+
return argument;
|
91
|
+
};
|
92
|
+
|
93
|
+
exports.Parser.prototype.act = function (args, options) {
|
94
|
+
if (!this._action) {
|
95
|
+
this.error(options, "Not yet implemented.");
|
96
|
+
this.exit(-1);
|
97
|
+
}
|
98
|
+
options.acted = true;
|
99
|
+
this._action.call(this, this.parse(args), options);
|
100
|
+
};
|
101
|
+
|
102
|
+
exports.Parser.prototype.action = function (action) {
|
103
|
+
if (this._action) {
|
104
|
+
action = (function (previous) {
|
105
|
+
return function () {
|
106
|
+
previous.apply(this, arguments);
|
107
|
+
action.apply(this, arguments);
|
108
|
+
};
|
109
|
+
})(action);
|
110
|
+
}
|
111
|
+
this._action = action;
|
112
|
+
return this;
|
113
|
+
};
|
114
|
+
|
115
|
+
// should be called last
|
116
|
+
exports.Parser.prototype.helpful = function () {
|
117
|
+
var self = this;
|
118
|
+
this.option('-h', '--help')
|
119
|
+
.help('displays usage information')
|
120
|
+
.action(function (options) {
|
121
|
+
return self.printHelp(options);
|
122
|
+
})
|
123
|
+
.halt();
|
124
|
+
if (util.len(this._commands))
|
125
|
+
this.command('help', function (options) {
|
126
|
+
self.printHelp(options);
|
127
|
+
}).help('displays usage information');
|
128
|
+
return this;
|
129
|
+
};
|
130
|
+
|
131
|
+
exports.Parser.prototype.usage = function (usage) {
|
132
|
+
this._usage = usage;
|
133
|
+
return this;
|
134
|
+
};
|
135
|
+
|
136
|
+
exports.Parser.prototype.help = function (help) {
|
137
|
+
this._help = help;
|
138
|
+
return this;
|
139
|
+
};
|
140
|
+
|
141
|
+
exports.Parser.prototype.printHelp = function (options) {
|
142
|
+
var args = options.args || [];
|
143
|
+
if (args.length) {
|
144
|
+
// parse args for deep help
|
145
|
+
// TODO offer extended help for options
|
146
|
+
if (!util.has(this._commands, args[0])) {
|
147
|
+
this.error(options, util.repr(args[0]) + ' is not a command.');
|
148
|
+
this.printCommands(options);
|
149
|
+
this.exit(options);
|
150
|
+
} else {
|
151
|
+
util.put(args, 1, '--help');
|
152
|
+
this._commands[args[0]]().act(args, options);
|
153
|
+
this.exit(options);
|
154
|
+
}
|
155
|
+
} else {
|
156
|
+
this.printUsage(options);
|
157
|
+
if (this._help)
|
158
|
+
this.print('' + this._help + '');
|
159
|
+
this.printCommands(options);
|
160
|
+
this.printOptions(options);
|
161
|
+
this.exit(options);
|
162
|
+
}
|
163
|
+
};
|
164
|
+
|
165
|
+
exports.Parser.prototype.printUsage = function (options) {
|
166
|
+
this.print(
|
167
|
+
'Usage: \0bold(\0blue(' + system.fs.basename(options.command || '<unknown>') + ' [OPTIONS]' +
|
168
|
+
(util.len(this._commands) ?
|
169
|
+
' COMMAND' :
|
170
|
+
''
|
171
|
+
) +
|
172
|
+
(util.len(this._args) ?
|
173
|
+
' ' + this._args.map(function (arg) {
|
174
|
+
if (arg._optional) {
|
175
|
+
return '[' + arg._name.toUpperCase() + ']';
|
176
|
+
} else {
|
177
|
+
return arg._name.toUpperCase();
|
178
|
+
}
|
179
|
+
}).join(' ') :
|
180
|
+
''
|
181
|
+
) +
|
182
|
+
(this._vargs ?
|
183
|
+
' [' + this._vargs._name.toUpperCase() + ' ...]':
|
184
|
+
''
|
185
|
+
) +
|
186
|
+
(this._usage ?
|
187
|
+
' ' + this._usage :
|
188
|
+
''
|
189
|
+
) + "\0)\0)"
|
190
|
+
);
|
191
|
+
};
|
192
|
+
|
193
|
+
exports.Parser.prototype.printCommands = function (options) {
|
194
|
+
var self = this;
|
195
|
+
util.forEachApply(
|
196
|
+
util.items(this._commands),
|
197
|
+
function (name, command) {
|
198
|
+
var parser = command();
|
199
|
+
self.print(' \0bold(\0green(' + name + '\0)\0)' + (
|
200
|
+
parser._help ?
|
201
|
+
(
|
202
|
+
': ' +
|
203
|
+
(
|
204
|
+
parser._action?
|
205
|
+
'': '\0red(NYI\0): '
|
206
|
+
) +
|
207
|
+
parser._help
|
208
|
+
) : ''
|
209
|
+
));
|
210
|
+
}
|
211
|
+
);
|
212
|
+
};
|
213
|
+
|
214
|
+
exports.Parser.prototype.printOption = function (options, option, depth, parent) {
|
215
|
+
var self = this;
|
216
|
+
depth = depth || 0;
|
217
|
+
var indent = util.mul(' ', depth);
|
218
|
+
|
219
|
+
if (option._hidden)
|
220
|
+
return;
|
221
|
+
if (option._group !== parent)
|
222
|
+
return;
|
223
|
+
|
224
|
+
if (option instanceof exports.Group) {
|
225
|
+
self.print(indent + ' \0yellow(' + option._name + ':\0)');
|
226
|
+
var parent = option;
|
227
|
+
option._options.forEach(function (option) {
|
228
|
+
return self.printOption(options, option, depth + 1, parent);
|
229
|
+
});
|
230
|
+
return;
|
231
|
+
}
|
232
|
+
|
233
|
+
var message = [];
|
234
|
+
if (option._short.length)
|
235
|
+
message.push(option._short.map(function (_short) {
|
236
|
+
return ' \0bold(\0green(-' + _short + '\0)\0)';
|
237
|
+
}).join(''));
|
238
|
+
if (option._long.length)
|
239
|
+
message.push(option._long.map(function (_long) {
|
240
|
+
return ' \0bold(\0green(--' + _long + '\0)\0)';
|
241
|
+
}).join(''));
|
242
|
+
if (option._action && option._action.length > 2)
|
243
|
+
message.push(
|
244
|
+
' ' +
|
245
|
+
util.range(option._action.length - 2)
|
246
|
+
.map(function () {
|
247
|
+
return '\0bold(\0green(' + util.upper(
|
248
|
+
option.getDisplayName()
|
249
|
+
) + '\0)\0)';
|
250
|
+
}).join(' ')
|
251
|
+
);
|
252
|
+
if (option._help)
|
253
|
+
message.push(': ' + option._help + '');
|
254
|
+
if (option._choices) {
|
255
|
+
var choices = option._choices;
|
256
|
+
if (!util.isArrayLike(choices))
|
257
|
+
choices = util.keys(choices);
|
258
|
+
message.push(' \0bold(\0blue((' + choices.join(', ') + ')\0)\0)');
|
259
|
+
}
|
260
|
+
if (option._halt)
|
261
|
+
message.push(' \0bold(\0blue((final option)\0)\0)');
|
262
|
+
self.print(indent + message.join(''));
|
263
|
+
|
264
|
+
};
|
265
|
+
|
266
|
+
exports.Parser.prototype.printOptions = function (options) {
|
267
|
+
var self = this;
|
268
|
+
self._options.forEach(function (option) {
|
269
|
+
self.printOption(options, option);
|
270
|
+
});
|
271
|
+
};
|
272
|
+
|
273
|
+
exports.Parser.prototype.error = function (options, message) {
|
274
|
+
if (this._parser) {
|
275
|
+
this._parser.error.apply(
|
276
|
+
this._parser,
|
277
|
+
arguments
|
278
|
+
);
|
279
|
+
} else {
|
280
|
+
this.print('\0red(' + message + '\0)');
|
281
|
+
this.exit();
|
282
|
+
}
|
283
|
+
};
|
284
|
+
|
285
|
+
exports.Parser.prototype.exit = function (status) {
|
286
|
+
if (this._parser) {
|
287
|
+
this._parser.exit.apply(
|
288
|
+
this._parser,
|
289
|
+
arguments
|
290
|
+
);
|
291
|
+
} else {
|
292
|
+
os.exit(status);
|
293
|
+
throw new Error("exit failed");
|
294
|
+
}
|
295
|
+
};
|
296
|
+
|
297
|
+
exports.Parser.prototype.print = function () {
|
298
|
+
if (this._parser)
|
299
|
+
this._parser.print.apply(
|
300
|
+
this._parser,
|
301
|
+
arguments
|
302
|
+
);
|
303
|
+
else
|
304
|
+
stream.print.apply(null, arguments);
|
305
|
+
};
|
306
|
+
|
307
|
+
// verifies that the parser is fully configured
|
308
|
+
exports.Parser.prototype.check = function () {
|
309
|
+
// make sure all options have associated actions
|
310
|
+
var self = this;
|
311
|
+
self._options.forEach(function (option) {
|
312
|
+
if (!(option instanceof self.Option))
|
313
|
+
return;
|
314
|
+
if (!option._action)
|
315
|
+
throw new exports.ConfigurationError(
|
316
|
+
"No action associated with the option " +
|
317
|
+
util.repr(option.getDisplayName())
|
318
|
+
);
|
319
|
+
});
|
320
|
+
};
|
321
|
+
|
322
|
+
// TODO break this into sub-functions
|
323
|
+
// TODO wrap with a try catch and print the progress through the arguments
|
324
|
+
exports.Parser.prototype.parse = function (args, options, noCommand) {
|
325
|
+
var self = this;
|
326
|
+
|
327
|
+
this.check();
|
328
|
+
|
329
|
+
if (!args)
|
330
|
+
args = system.args;
|
331
|
+
if (!options)
|
332
|
+
options = {};
|
333
|
+
|
334
|
+
options.args = args;
|
335
|
+
if (!noCommand && args.length && !/^-/.test(args[0]))
|
336
|
+
options.command = args.shift();
|
337
|
+
|
338
|
+
function mandatoryShift(n, name) {
|
339
|
+
if (n > args.length) {
|
340
|
+
this.error(
|
341
|
+
options,
|
342
|
+
'Error: The ' + util.enquote(name) +
|
343
|
+
' option requires ' + n + ' arguments.'
|
344
|
+
);
|
345
|
+
}
|
346
|
+
var result = args.slice(0, n);
|
347
|
+
for (var i = 0; i < n; i++)
|
348
|
+
args.shift()
|
349
|
+
return result;
|
350
|
+
};
|
351
|
+
|
352
|
+
function validate(option, value) {
|
353
|
+
try {
|
354
|
+
return option._validate.call(self, value);
|
355
|
+
} catch (exception) {
|
356
|
+
self.error(options, exception);
|
357
|
+
}
|
358
|
+
};
|
359
|
+
|
360
|
+
// initial values
|
361
|
+
for (var name in this._def) {
|
362
|
+
if (util.has(this._def, name) && !util.has(options, name))
|
363
|
+
options[name] = util.copy(this._def[name]);
|
364
|
+
}
|
365
|
+
this._options.forEach(function (option) {
|
366
|
+
if (!(option instanceof self.Option))
|
367
|
+
return;
|
368
|
+
if (!util.has(options, option.getName()))
|
369
|
+
options[option.getName()] = option._def;
|
370
|
+
});
|
371
|
+
|
372
|
+
// walk args
|
373
|
+
ARGS: while (args.length) {
|
374
|
+
var arg = args.shift();
|
375
|
+
if (arg == "--") {
|
376
|
+
break;
|
377
|
+
|
378
|
+
} else if (/^--/.test(arg)) {
|
379
|
+
|
380
|
+
var pattern = arg.match(/^--([^=]+)(?:=(.*))?/).slice(1);
|
381
|
+
var word = pattern[0];
|
382
|
+
var value = pattern[1];
|
383
|
+
|
384
|
+
if (!!value) {
|
385
|
+
args.unshift(value);
|
386
|
+
}
|
387
|
+
|
388
|
+
if (util.has(this._long, word)) {
|
389
|
+
|
390
|
+
var option = this._long[word];
|
391
|
+
if (!option._action) {
|
392
|
+
self.error(
|
393
|
+
options,
|
394
|
+
"Programmer error: The " + word +
|
395
|
+
" option does not have an associated action."
|
396
|
+
);
|
397
|
+
}
|
398
|
+
|
399
|
+
option._action.apply(
|
400
|
+
self,
|
401
|
+
[
|
402
|
+
options,
|
403
|
+
option.getName()
|
404
|
+
].concat(
|
405
|
+
validate(option, mandatoryShift.call(
|
406
|
+
this,
|
407
|
+
Math.max(0, option._action.length - 2),
|
408
|
+
option.getName()
|
409
|
+
))
|
410
|
+
)
|
411
|
+
);
|
412
|
+
|
413
|
+
if (option._halt)
|
414
|
+
break ARGS;
|
415
|
+
|
416
|
+
} else {
|
417
|
+
this.error(options, 'Error: Unrecognized option: ' + util.enquote(word));
|
418
|
+
}
|
419
|
+
|
420
|
+
} else if (/^-/.test(arg)) {
|
421
|
+
|
422
|
+
var letters = arg.match(/^-(.*)/)[1].split('');
|
423
|
+
while (letters.length) {
|
424
|
+
var letter = letters.shift();
|
425
|
+
if (util.has(this._short, letter)) {
|
426
|
+
var option = this._short[letter];
|
427
|
+
|
428
|
+
if (option._action.length > 2) {
|
429
|
+
if (letters.length) {
|
430
|
+
args.unshift(letters.join(''));
|
431
|
+
letters = [];
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
option._action.apply(
|
436
|
+
self,
|
437
|
+
[
|
438
|
+
options,
|
439
|
+
option.getName(),
|
440
|
+
].concat(
|
441
|
+
validate(
|
442
|
+
option,
|
443
|
+
mandatoryShift.call(
|
444
|
+
this,
|
445
|
+
Math.max(0, option._action.length - 2),
|
446
|
+
option.getName()
|
447
|
+
)
|
448
|
+
)
|
449
|
+
)
|
450
|
+
);
|
451
|
+
|
452
|
+
if (option._halt)
|
453
|
+
break ARGS;
|
454
|
+
|
455
|
+
} else {
|
456
|
+
this.error(options, 'Error: unrecognized option: ' + util.enquote(letter));
|
457
|
+
}
|
458
|
+
}
|
459
|
+
|
460
|
+
} else {
|
461
|
+
// TODO permit options interleaved with arguments,
|
462
|
+
// with associated actions, for any of positional
|
463
|
+
// args, variadic args, and accumulated args
|
464
|
+
args.unshift(arg);
|
465
|
+
break;
|
466
|
+
}
|
467
|
+
|
468
|
+
}
|
469
|
+
|
470
|
+
if (util.len(this._commands)) {
|
471
|
+
if (args.length) {
|
472
|
+
if (util.has(this._commands, args[0])) {
|
473
|
+
var command = this._commands[args[0]];
|
474
|
+
command().act(args, options);
|
475
|
+
} else {
|
476
|
+
this.error(options, 'Error: unrecognized command');
|
477
|
+
}
|
478
|
+
} else {
|
479
|
+
this.error(options, 'Error: command required');
|
480
|
+
this.exit(0);
|
481
|
+
}
|
482
|
+
}
|
483
|
+
|
484
|
+
return options;
|
485
|
+
};
|
486
|
+
|
487
|
+
exports.Argument = function (parser) {
|
488
|
+
this._parser = parser;
|
489
|
+
return this;
|
490
|
+
};
|
491
|
+
|
492
|
+
exports.Argument.prototype.name = function (name) {
|
493
|
+
this._name = name;
|
494
|
+
return this;
|
495
|
+
};
|
496
|
+
|
497
|
+
exports.Argument.prototype.optional = function () {
|
498
|
+
this._optional = true;
|
499
|
+
return this;
|
500
|
+
};
|
501
|
+
|
502
|
+
exports.Option = function (parser, args) {
|
503
|
+
var self = this;
|
504
|
+
this._parser = parser;
|
505
|
+
this._validate = function (value) {
|
506
|
+
return value;
|
507
|
+
};
|
508
|
+
this._long = [];
|
509
|
+
this._short = [];
|
510
|
+
util.forEach(args, function (arg) {
|
511
|
+
if (typeof arg == "function") {
|
512
|
+
self.action(arg);
|
513
|
+
} else if (typeof arg !== "string") {
|
514
|
+
for (var name in arg) {
|
515
|
+
var value = arg[name];
|
516
|
+
self[name](value);
|
517
|
+
}
|
518
|
+
} else if (/ /.test(arg)) {
|
519
|
+
self.help(arg);
|
520
|
+
} else if (/^--/.test(arg)) {
|
521
|
+
arg = arg.match(/^--(.*)/)[1];
|
522
|
+
self.__(arg);
|
523
|
+
} else if (/^-.$/.test(arg)) {
|
524
|
+
arg = arg.match(/^-(.)/)[1];
|
525
|
+
self._(arg);
|
526
|
+
} else if (/^-/.test(arg)) {
|
527
|
+
throw new Error("option names with one dash can only have one letter.");
|
528
|
+
} else {
|
529
|
+
if (!self._name) {
|
530
|
+
self.name(arg);
|
531
|
+
self.displayName(arg);
|
532
|
+
} else {
|
533
|
+
self.name(arg);
|
534
|
+
}
|
535
|
+
}
|
536
|
+
});
|
537
|
+
if (!(self._short.length || self._long.length || self._name))
|
538
|
+
throw new exports.ConfigurationError("Option has no name.");
|
539
|
+
return this;
|
540
|
+
};
|
541
|
+
|
542
|
+
exports.Option.prototype._ = function (letter) {
|
543
|
+
this._short.push(letter);
|
544
|
+
this._parser._short[letter] = this;
|
545
|
+
return this;
|
546
|
+
};
|
547
|
+
|
548
|
+
exports.Option.prototype.__ = function (word) {
|
549
|
+
this._long.push(word);
|
550
|
+
this._parser._long[word] = this;
|
551
|
+
return this;
|
552
|
+
};
|
553
|
+
|
554
|
+
exports.Option.prototype.name = function (name) {
|
555
|
+
this._name = name;
|
556
|
+
return this;
|
557
|
+
};
|
558
|
+
|
559
|
+
exports.Option.prototype.displayName = function (displayName) {
|
560
|
+
this._displayName = displayName;
|
561
|
+
return this;
|
562
|
+
};
|
563
|
+
|
564
|
+
exports.Option.prototype.getDisplayName = function () {
|
565
|
+
if (this._displayName)
|
566
|
+
return this._displayName;
|
567
|
+
return this.getName();
|
568
|
+
};
|
569
|
+
|
570
|
+
exports.Option.prototype.getName = function () {
|
571
|
+
if (this._name) {
|
572
|
+
return this._name;
|
573
|
+
}
|
574
|
+
if (this._long.length > 0) {
|
575
|
+
return this._long[0];
|
576
|
+
}
|
577
|
+
if (this._short.length > 0) {
|
578
|
+
return this._short[0];
|
579
|
+
}
|
580
|
+
throw new Error("Programmer error: unnamed option");
|
581
|
+
};
|
582
|
+
|
583
|
+
exports.Option.prototype.action = function (action) {
|
584
|
+
var self = this;
|
585
|
+
if (typeof action == "string") {
|
586
|
+
this._action = self._parser[action];
|
587
|
+
} else {
|
588
|
+
this._action = action;
|
589
|
+
}
|
590
|
+
return this;
|
591
|
+
};
|
592
|
+
|
593
|
+
exports.Option.prototype.set = function (value) {
|
594
|
+
var option = this;
|
595
|
+
if (arguments.length == 0)
|
596
|
+
return this.action(function (options, name, value) {
|
597
|
+
options[name] = value;
|
598
|
+
});
|
599
|
+
else if (arguments.length == 1)
|
600
|
+
return this.action(function (options, name) {
|
601
|
+
options[name] = value;
|
602
|
+
});
|
603
|
+
else
|
604
|
+
throw new exports.UsageError("Option().set takes 0 or 1 arguments");
|
605
|
+
};
|
606
|
+
|
607
|
+
exports.Option.prototype.push = function () {
|
608
|
+
var option = this;
|
609
|
+
return this.def([]).action(function (options, name, value) {
|
610
|
+
options[name].push(option._validate.call(
|
611
|
+
this,
|
612
|
+
value
|
613
|
+
));
|
614
|
+
});
|
615
|
+
};
|
616
|
+
|
617
|
+
exports.Option.prototype.inc = function () {
|
618
|
+
return this.def(0).action(function (options, name) {
|
619
|
+
options[name]++;
|
620
|
+
});
|
621
|
+
};
|
622
|
+
|
623
|
+
exports.Option.prototype.dec = function () {
|
624
|
+
return this.def(0).action(function (options, name) {
|
625
|
+
options[name]--;
|
626
|
+
});
|
627
|
+
};
|
628
|
+
|
629
|
+
exports.Option.prototype.choices = function (choices) {
|
630
|
+
this.set();
|
631
|
+
this._choices = choices;
|
632
|
+
var self = this;
|
633
|
+
if (util.isArrayLike(choices)) {
|
634
|
+
return this.validate(function (value) {
|
635
|
+
if (choices.indexOf(value) < 0)
|
636
|
+
throw new exports.UsageError(
|
637
|
+
"choice for " + util.upper(self.getDisplayName()) +
|
638
|
+
" is invalid: " + util.enquote(value) + "\n" +
|
639
|
+
"Use one of: " + choices.map(function (choice) {
|
640
|
+
return util.enquote(choice);
|
641
|
+
}).join(', ')
|
642
|
+
);
|
643
|
+
return value;
|
644
|
+
})
|
645
|
+
} else {
|
646
|
+
return this.validate(function (value) {
|
647
|
+
if (!util.has(choices, value))
|
648
|
+
throw new exports.UsageError(
|
649
|
+
"choice for " + util.upper(self.getDisplayName()) +
|
650
|
+
" is invalid: " + util.enquote(value) + "\n" +
|
651
|
+
"Use one of: " + util.keys(choices).map(function (choice) {
|
652
|
+
return util.enquote(choice);
|
653
|
+
}).join(', ')
|
654
|
+
);
|
655
|
+
return choices[value];
|
656
|
+
});
|
657
|
+
}
|
658
|
+
};
|
659
|
+
|
660
|
+
exports.Option.prototype.def = function (value) {
|
661
|
+
if (this._def === undefined)
|
662
|
+
this._def = value;
|
663
|
+
return this;
|
664
|
+
};
|
665
|
+
|
666
|
+
exports.Option.prototype.validate = function (validate) {
|
667
|
+
var current = this._validate;
|
668
|
+
if (this._validate) {
|
669
|
+
validate = (function (previous) {
|
670
|
+
return function () {
|
671
|
+
return current.call(
|
672
|
+
this,
|
673
|
+
previous.apply(this, arguments)
|
674
|
+
);
|
675
|
+
};
|
676
|
+
})(validate);
|
677
|
+
}
|
678
|
+
this._validate = validate;
|
679
|
+
return this;
|
680
|
+
};
|
681
|
+
|
682
|
+
exports.Option.prototype.input = function () {
|
683
|
+
this.set().validate(function (value) {
|
684
|
+
if (value == "-")
|
685
|
+
return system.stdin;
|
686
|
+
else
|
687
|
+
return system.fs.open(value, 'r');
|
688
|
+
});
|
689
|
+
};
|
690
|
+
|
691
|
+
exports.Option.prototype.output = function () {
|
692
|
+
this.set().validate(function (value) {
|
693
|
+
if (value == "-")
|
694
|
+
return system.stdout;
|
695
|
+
else
|
696
|
+
return system.fs.open(value, 'w');
|
697
|
+
});
|
698
|
+
};
|
699
|
+
|
700
|
+
exports.Option.prototype.number = function () {
|
701
|
+
return this.set().validate(function (value) {
|
702
|
+
var result = +value;
|
703
|
+
if (isNaN(result))
|
704
|
+
throw new exports.UsageError("not a number");
|
705
|
+
return result;
|
706
|
+
});
|
707
|
+
};
|
708
|
+
|
709
|
+
exports.Option.prototype.oct = function () {
|
710
|
+
return this.set().validate(function (value) {
|
711
|
+
var result = parseInt(value, 8);
|
712
|
+
if (isNaN(result))
|
713
|
+
throw new exports.UsageError("not an octal value");
|
714
|
+
return result;
|
715
|
+
});
|
716
|
+
};
|
717
|
+
|
718
|
+
exports.Option.prototype.hex = function () {
|
719
|
+
return this.set().validate(function (value) {
|
720
|
+
var result = parseInt(value, 16);
|
721
|
+
if (isNaN(result))
|
722
|
+
throw new exports.UsageError("not an hex value");
|
723
|
+
return result;
|
724
|
+
});
|
725
|
+
};
|
726
|
+
|
727
|
+
exports.Option.prototype.integer = function () {
|
728
|
+
return this.set().validate(function (value) {
|
729
|
+
var result = parseInt(value, 10);
|
730
|
+
if (isNaN(result) || result !== +value)
|
731
|
+
throw new exports.UsageError("not an integer");
|
732
|
+
return result;
|
733
|
+
});
|
734
|
+
};
|
735
|
+
|
736
|
+
exports.Option.prototype.natural = function () {
|
737
|
+
return this.set().validate(function (value) {
|
738
|
+
var result = value >>> 0;
|
739
|
+
if (result !== +value || result < 0)
|
740
|
+
throw new exports.UsageError("not a natural number");
|
741
|
+
return result;
|
742
|
+
});
|
743
|
+
};
|
744
|
+
|
745
|
+
exports.Option.prototype.whole = function () {
|
746
|
+
return this.set().validate(function (value) {
|
747
|
+
var result = value >>> 0;
|
748
|
+
if (result !== +value || result < 1)
|
749
|
+
throw new exports.UsageError("not a whole number");
|
750
|
+
return result;
|
751
|
+
});
|
752
|
+
};
|
753
|
+
|
754
|
+
exports.Option.prototype.bool = function (def) {
|
755
|
+
if (def === undefined)
|
756
|
+
def = true;
|
757
|
+
return this.def(!def).set(!!def);
|
758
|
+
};
|
759
|
+
|
760
|
+
exports.Option.prototype.todo = function (command, value) {
|
761
|
+
this._parser.def('todo', []);
|
762
|
+
command = command || this.getName();
|
763
|
+
if (value)
|
764
|
+
return this.action(function (options, name, value) {
|
765
|
+
options.todo.push([command, value]);
|
766
|
+
});
|
767
|
+
else
|
768
|
+
return this.action(function (options, name) {
|
769
|
+
options.todo.push([command]);
|
770
|
+
});
|
771
|
+
};
|
772
|
+
|
773
|
+
exports.Option.prototype.inverse = function () {
|
774
|
+
var args = arguments;
|
775
|
+
if (!args.length) {
|
776
|
+
args = [];
|
777
|
+
this._short.forEach(function (_) {
|
778
|
+
args.push('-' + _.toUpperCase());
|
779
|
+
});
|
780
|
+
this._long.forEach(function (__) {
|
781
|
+
args.push('--no-' + __);
|
782
|
+
});
|
783
|
+
if (this.getName())
|
784
|
+
args.push(this.getName());
|
785
|
+
}
|
786
|
+
var parser = this._parser;
|
787
|
+
var inverse = this._inverse = parser.option.apply(
|
788
|
+
parser,
|
789
|
+
args
|
790
|
+
).set(!this._def).help('^ inverse');
|
791
|
+
return this;
|
792
|
+
};
|
793
|
+
|
794
|
+
exports.Option.prototype.help = function (text) {
|
795
|
+
this._help = text;
|
796
|
+
return this;
|
797
|
+
};
|
798
|
+
|
799
|
+
exports.Option.prototype.halt = function () {
|
800
|
+
this._halt = true;
|
801
|
+
return this;
|
802
|
+
};
|
803
|
+
|
804
|
+
exports.Option.prototype.hidden = function () {
|
805
|
+
this._hidden = true;
|
806
|
+
return this;
|
807
|
+
};
|
808
|
+
|
809
|
+
exports.Option.prototype.end = function () {
|
810
|
+
return this._parser;
|
811
|
+
};
|
812
|
+
|
813
|
+
exports.Option.prototype.option = function () {
|
814
|
+
return this.end().option.apply(this, arguments);
|
815
|
+
};
|
816
|
+
|
817
|
+
exports.Parser.prototype.end = function () {
|
818
|
+
return this._parser;
|
819
|
+
};
|
820
|
+
|
821
|
+
exports.Group = function (parser, parent, name) {
|
822
|
+
this._name = name;
|
823
|
+
this._parser = parser;
|
824
|
+
this._parent = parent;
|
825
|
+
this._options = [];
|
826
|
+
return this;
|
827
|
+
};
|
828
|
+
|
829
|
+
exports.Group.prototype.option = function () {
|
830
|
+
var option = this._parser.option.apply(this._parser, arguments);
|
831
|
+
option._group = this;
|
832
|
+
this._options.push(option);
|
833
|
+
return option;
|
834
|
+
};
|
835
|
+
|
836
|
+
exports.Group.prototype.group = function (name) {
|
837
|
+
var Group = this.Group || this._parser.Group;
|
838
|
+
var group = new Group(this._parser, this, name);
|
839
|
+
return group;
|
840
|
+
};
|
841
|
+
|
842
|
+
exports.Group.prototype.end = function () {
|
843
|
+
return this._parent;
|
844
|
+
};
|
845
|
+
|
846
|
+
exports.Parser.prototype.Parser = exports.Parser;
|
847
|
+
exports.Parser.prototype.Option = exports.Option;
|
848
|
+
exports.Parser.prototype.Group = exports.Group;
|
849
|
+
|