macgyver 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +20 -0
  5. data/README.md +45 -0
  6. data/Rakefile +1 -0
  7. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Growl +0 -0
  8. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Growl +0 -0
  9. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/Growl.h +5 -0
  10. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h +551 -0
  11. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h +341 -0
  12. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Resources/Info.plist +40 -0
  13. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/_CodeSignature/CodeResources +34 -0
  14. data/assets/MacGap.app/Contents/Info.plist +48 -0
  15. data/assets/MacGap.app/Contents/MacOS/MacGap +0 -0
  16. data/assets/MacGap.app/Contents/PkgInfo +1 -0
  17. data/assets/MacGap.app/Contents/Resources/_debugger.js +1718 -0
  18. data/assets/MacGap.app/Contents/Resources/_http_agent.js +310 -0
  19. data/assets/MacGap.app/Contents/Resources/_http_client.js +533 -0
  20. data/assets/MacGap.app/Contents/Resources/_http_common.js +222 -0
  21. data/assets/MacGap.app/Contents/Resources/_http_incoming.js +194 -0
  22. data/assets/MacGap.app/Contents/Resources/_http_outgoing.js +597 -0
  23. data/assets/MacGap.app/Contents/Resources/_http_server.js +510 -0
  24. data/assets/MacGap.app/Contents/Resources/_linklist.js +76 -0
  25. data/assets/MacGap.app/Contents/Resources/_stream_duplex.js +69 -0
  26. data/assets/MacGap.app/Contents/Resources/_stream_passthrough.js +41 -0
  27. data/assets/MacGap.app/Contents/Resources/_stream_readable.js +900 -0
  28. data/assets/MacGap.app/Contents/Resources/_stream_transform.js +204 -0
  29. data/assets/MacGap.app/Contents/Resources/_stream_writable.js +456 -0
  30. data/assets/MacGap.app/Contents/Resources/_tls_legacy.js +887 -0
  31. data/assets/MacGap.app/Contents/Resources/_tls_wrap.js +831 -0
  32. data/assets/MacGap.app/Contents/Resources/application.icns +0 -0
  33. data/assets/MacGap.app/Contents/Resources/assert.js +326 -0
  34. data/assets/MacGap.app/Contents/Resources/buffer.js +724 -0
  35. data/assets/MacGap.app/Contents/Resources/child_process.js +1107 -0
  36. data/assets/MacGap.app/Contents/Resources/cluster.js +613 -0
  37. data/assets/MacGap.app/Contents/Resources/console.js +108 -0
  38. data/assets/MacGap.app/Contents/Resources/constants.js +22 -0
  39. data/assets/MacGap.app/Contents/Resources/crypto.js +691 -0
  40. data/assets/MacGap.app/Contents/Resources/dgram.js +459 -0
  41. data/assets/MacGap.app/Contents/Resources/dns.js +274 -0
  42. data/assets/MacGap.app/Contents/Resources/domain.js +292 -0
  43. data/assets/MacGap.app/Contents/Resources/en.lproj/Credits.rtf +29 -0
  44. data/assets/MacGap.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  45. data/assets/MacGap.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
  46. data/assets/MacGap.app/Contents/Resources/en.lproj/Window.nib +0 -0
  47. data/assets/MacGap.app/Contents/Resources/events.js +312 -0
  48. data/assets/MacGap.app/Contents/Resources/freelist.js +43 -0
  49. data/assets/MacGap.app/Contents/Resources/fs.js +1732 -0
  50. data/assets/MacGap.app/Contents/Resources/http.js +119 -0
  51. data/assets/MacGap.app/Contents/Resources/https.js +134 -0
  52. data/assets/MacGap.app/Contents/Resources/module.js +529 -0
  53. data/assets/MacGap.app/Contents/Resources/net.js +1378 -0
  54. data/assets/MacGap.app/Contents/Resources/nodelike.js +195 -0
  55. data/assets/MacGap.app/Contents/Resources/os.js +64 -0
  56. data/assets/MacGap.app/Contents/Resources/path.js +517 -0
  57. data/assets/MacGap.app/Contents/Resources/public/index.html +38 -0
  58. data/assets/MacGap.app/Contents/Resources/punycode.js +507 -0
  59. data/assets/MacGap.app/Contents/Resources/querystring.js +206 -0
  60. data/assets/MacGap.app/Contents/Resources/readline.js +1311 -0
  61. data/assets/MacGap.app/Contents/Resources/repl.js +945 -0
  62. data/assets/MacGap.app/Contents/Resources/smalloc.js +90 -0
  63. data/assets/MacGap.app/Contents/Resources/stream.js +127 -0
  64. data/assets/MacGap.app/Contents/Resources/string_decoder.js +189 -0
  65. data/assets/MacGap.app/Contents/Resources/sys.js +24 -0
  66. data/assets/MacGap.app/Contents/Resources/timers.js +568 -0
  67. data/assets/MacGap.app/Contents/Resources/tls.js +220 -0
  68. data/assets/MacGap.app/Contents/Resources/tty.js +129 -0
  69. data/assets/MacGap.app/Contents/Resources/url.js +693 -0
  70. data/assets/MacGap.app/Contents/Resources/util.js +688 -0
  71. data/assets/MacGap.app/Contents/Resources/vm.js +73 -0
  72. data/assets/MacGap.app/Contents/Resources/zlib.js +524 -0
  73. data/assets/index.html +38 -0
  74. data/bin/macgyver +104 -0
  75. data/macgyver.gemspec +19 -0
  76. data/test/public/index.html +27 -0
  77. metadata +121 -0
@@ -0,0 +1,945 @@
1
+ // Copyright Joyent, Inc. and other Node contributors.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a
4
+ // copy of this software and associated documentation files (the
5
+ // "Software"), to deal in the Software without restriction, including
6
+ // without limitation the rights to use, copy, modify, merge, publish,
7
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ // persons to whom the Software is furnished to do so, subject to the
9
+ // following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included
12
+ // in all copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ /* A repl library that you can include in your own code to get a runtime
23
+ * interface to your program.
24
+ *
25
+ * var repl = require("repl");
26
+ * // start repl on stdin
27
+ * repl.start("prompt> ");
28
+ *
29
+ * // listen for unix socket connections and start repl on them
30
+ * net.createServer(function(socket) {
31
+ * repl.start("node via Unix socket> ", socket);
32
+ * }).listen("/tmp/node-repl-sock");
33
+ *
34
+ * // listen for TCP socket connections and start repl on them
35
+ * net.createServer(function(socket) {
36
+ * repl.start("node via TCP socket> ", socket);
37
+ * }).listen(5001);
38
+ *
39
+ * // expose foo to repl context
40
+ * repl.start("node > ").context.foo = "stdin is fun";
41
+ */
42
+
43
+ var util = require('util');
44
+ var inherits = require('util').inherits;
45
+ var Stream = require('stream');
46
+ var vm = require('vm');
47
+ var path = require('path');
48
+ var fs = require('fs');
49
+ var rl = require('readline');
50
+ var Console = require('console').Console;
51
+ var EventEmitter = require('events').EventEmitter;
52
+ var domain = require('domain');
53
+ var debug = util.debuglog('repl');
54
+
55
+ // If obj.hasOwnProperty has been overridden, then calling
56
+ // obj.hasOwnProperty(prop) will break.
57
+ // See: https://github.com/joyent/node/issues/1707
58
+ function hasOwnProperty(obj, prop) {
59
+ return Object.prototype.hasOwnProperty.call(obj, prop);
60
+ }
61
+
62
+
63
+ // hack for require.resolve("./relative") to work properly.
64
+ module.filename = path.resolve('repl');
65
+
66
+ // hack for repl require to work properly with node_modules folders
67
+ module.paths = require('module')._nodeModulePaths(module.filename);
68
+
69
+ // Can overridden with custom print functions, such as `probe` or `eyes.js`.
70
+ // This is the default "writer" value if none is passed in the REPL options.
71
+ exports.writer = util.inspect;
72
+
73
+ exports._builtinLibs = ['assert', 'buffer', 'child_process', 'cluster',
74
+ 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net',
75
+ 'os', 'path', 'punycode', 'querystring', 'readline', 'stream',
76
+ 'string_decoder', 'tls', 'tty', 'url', 'util', 'vm', 'zlib', 'smalloc'];
77
+
78
+
79
+ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
80
+ if (!(this instanceof REPLServer)) {
81
+ return new REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined);
82
+ }
83
+
84
+ EventEmitter.call(this);
85
+
86
+ var options, input, output, dom;
87
+ if (util.isObject(prompt)) {
88
+ // an options object was given
89
+ options = prompt;
90
+ stream = options.stream || options.socket;
91
+ input = options.input;
92
+ output = options.output;
93
+ eval_ = options.eval;
94
+ useGlobal = options.useGlobal;
95
+ ignoreUndefined = options.ignoreUndefined;
96
+ prompt = options.prompt;
97
+ dom = options.domain;
98
+ } else if (!util.isString(prompt)) {
99
+ throw new Error('An options Object, or a prompt String are required');
100
+ } else {
101
+ options = {};
102
+ }
103
+
104
+ var self = this;
105
+
106
+ self._domain = dom || domain.create();
107
+
108
+ self.useGlobal = !!useGlobal;
109
+ self.ignoreUndefined = !!ignoreUndefined;
110
+
111
+ eval_ = eval_ || defaultEval;
112
+
113
+ function defaultEval(code, context, file, cb) {
114
+ var err, result;
115
+ // first, create the Script object to check the syntax
116
+ try {
117
+ var script = vm.createScript(code, {
118
+ filename: file,
119
+ displayErrors: false
120
+ });
121
+ } catch (e) {
122
+ err = e;
123
+ debug('parse error %j', code, e);
124
+ }
125
+
126
+ if (!err) {
127
+ try {
128
+ if (self.useGlobal) {
129
+ result = script.runInThisContext({ displayErrors: false });
130
+ } else {
131
+ result = script.runInContext(context, { displayErrors: false });
132
+ }
133
+ } catch (e) {
134
+ err = e;
135
+ if (err && process.domain) {
136
+ debug('not recoverable, send to domain');
137
+ process.domain.emit('error', err);
138
+ process.domain.exit();
139
+ return;
140
+ }
141
+ }
142
+ }
143
+
144
+ cb(err, result);
145
+ }
146
+
147
+ self.eval = self._domain.bind(eval_);
148
+
149
+ self._domain.on('error', function(e) {
150
+ debug('domain error');
151
+ self.outputStream.write((e.stack || e) + '\n');
152
+ self.bufferedCommand = '';
153
+ self.lines.level = [];
154
+ self.displayPrompt();
155
+ });
156
+
157
+ if (!input && !output) {
158
+ // legacy API, passing a 'stream'/'socket' option
159
+ if (!stream) {
160
+ // use stdin and stdout as the default streams if none were given
161
+ stream = process;
162
+ }
163
+ if (stream.stdin && stream.stdout) {
164
+ // We're given custom object with 2 streams, or the `process` object
165
+ input = stream.stdin;
166
+ output = stream.stdout;
167
+ } else {
168
+ // We're given a duplex readable/writable Stream, like a `net.Socket`
169
+ input = stream;
170
+ output = stream;
171
+ }
172
+ }
173
+
174
+ self.inputStream = input;
175
+ self.outputStream = output;
176
+
177
+ self.resetContext();
178
+ self.bufferedCommand = '';
179
+ self.lines.level = [];
180
+
181
+ self.prompt = !util.isUndefined(prompt) ? prompt : '> ';
182
+
183
+ function complete(text, callback) {
184
+ self.complete(text, callback);
185
+ }
186
+
187
+ var rli = rl.createInterface({
188
+ input: self.inputStream,
189
+ output: self.outputStream,
190
+ completer: complete,
191
+ terminal: options.terminal
192
+ });
193
+ self.rli = rli;
194
+
195
+ this.commands = {};
196
+ defineDefaultCommands(this);
197
+
198
+ // figure out which "writer" function to use
199
+ self.writer = options.writer || exports.writer;
200
+
201
+ if (util.isUndefined(options.useColors)) {
202
+ options.useColors = rli.terminal;
203
+ }
204
+ self.useColors = !!options.useColors;
205
+
206
+ if (self.useColors && self.writer === util.inspect) {
207
+ // Turn on ANSI coloring.
208
+ self.writer = function(obj, showHidden, depth) {
209
+ return util.inspect(obj, showHidden, depth, true);
210
+ };
211
+ }
212
+
213
+ rli.setPrompt(self.prompt);
214
+
215
+ rli.on('close', function() {
216
+ self.emit('exit');
217
+ });
218
+
219
+ var sawSIGINT = false;
220
+ rli.on('SIGINT', function() {
221
+ var empty = rli.line.length === 0;
222
+ rli.clearLine();
223
+
224
+ if (!(self.bufferedCommand && self.bufferedCommand.length > 0) && empty) {
225
+ if (sawSIGINT) {
226
+ rli.close();
227
+ sawSIGINT = false;
228
+ return;
229
+ }
230
+ rli.output.write('(^C again to quit)\n');
231
+ sawSIGINT = true;
232
+ } else {
233
+ sawSIGINT = false;
234
+ }
235
+
236
+ self.bufferedCommand = '';
237
+ self.lines.level = [];
238
+ self.displayPrompt();
239
+ });
240
+
241
+ rli.on('line', function(cmd) {
242
+ debug('line %j', cmd);
243
+ sawSIGINT = false;
244
+ var skipCatchall = false;
245
+ cmd = trimWhitespace(cmd);
246
+
247
+ // Check to see if a REPL keyword was used. If it returns true,
248
+ // display next prompt and return.
249
+ if (cmd && cmd.charAt(0) === '.' && isNaN(parseFloat(cmd))) {
250
+ var matches = cmd.match(/^(\.[^\s]+)\s*(.*)$/);
251
+ var keyword = matches && matches[1];
252
+ var rest = matches && matches[2];
253
+ if (self.parseREPLKeyword(keyword, rest) === true) {
254
+ return;
255
+ } else {
256
+ self.outputStream.write('Invalid REPL keyword\n');
257
+ skipCatchall = true;
258
+ }
259
+ }
260
+
261
+ if (!skipCatchall) {
262
+ var evalCmd = self.bufferedCommand + cmd;
263
+ if (/^\s*\{/.test(evalCmd) && /\}\s*$/.test(evalCmd)) {
264
+ // It's confusing for `{ a : 1 }` to be interpreted as a block
265
+ // statement rather than an object literal. So, we first try
266
+ // to wrap it in parentheses, so that it will be interpreted as
267
+ // an expression.
268
+ evalCmd = '(' + evalCmd + ')\n';
269
+ } else {
270
+ // otherwise we just append a \n so that it will be either
271
+ // terminated, or continued onto the next expression if it's an
272
+ // unexpected end of input.
273
+ evalCmd = evalCmd + '\n';
274
+ }
275
+
276
+ debug('eval %j', evalCmd);
277
+ self.eval(evalCmd, self.context, 'repl', finish);
278
+ } else {
279
+ finish(null);
280
+ }
281
+
282
+ function finish(e, ret) {
283
+ debug('finish', e, ret);
284
+ self.memory(cmd);
285
+
286
+ if (e && !self.bufferedCommand && cmd.trim().match(/^npm /)) {
287
+ self.outputStream.write('npm should be run outside of the ' +
288
+ 'node repl, in your normal shell.\n' +
289
+ '(Press Control-D to exit.)\n');
290
+ self.bufferedCommand = '';
291
+ self.displayPrompt();
292
+ return;
293
+ }
294
+
295
+ // If error was SyntaxError and not JSON.parse error
296
+ if (e) {
297
+ if (isRecoverableError(e)) {
298
+ // Start buffering data like that:
299
+ // {
300
+ // ... x: 1
301
+ // ... }
302
+ self.bufferedCommand += cmd + '\n';
303
+ self.displayPrompt();
304
+ return;
305
+ } else {
306
+ self._domain.emit('error', e);
307
+ }
308
+ }
309
+
310
+ // Clear buffer if no SyntaxErrors
311
+ self.bufferedCommand = '';
312
+
313
+ // If we got any output - print it (if no error)
314
+ if (!e && (!self.ignoreUndefined || !util.isUndefined(ret))) {
315
+ self.context._ = ret;
316
+ self.outputStream.write(self.writer(ret) + '\n');
317
+ }
318
+
319
+ // Display prompt again
320
+ self.displayPrompt();
321
+ };
322
+ });
323
+
324
+ rli.on('SIGCONT', function() {
325
+ self.displayPrompt(true);
326
+ });
327
+
328
+ self.displayPrompt();
329
+ }
330
+ inherits(REPLServer, EventEmitter);
331
+ exports.REPLServer = REPLServer;
332
+
333
+
334
+ // prompt is a string to print on each line for the prompt,
335
+ // source is a stream to use for I/O, defaulting to stdin/stdout.
336
+ exports.start = function(prompt, source, eval_, useGlobal, ignoreUndefined) {
337
+ var repl = new REPLServer(prompt, source, eval_, useGlobal, ignoreUndefined);
338
+ if (!exports.repl) exports.repl = repl;
339
+ return repl;
340
+ };
341
+
342
+
343
+ REPLServer.prototype.createContext = function() {
344
+ var context;
345
+ if (this.useGlobal) {
346
+ context = global;
347
+ } else {
348
+ context = vm.createContext();
349
+ for (var i in global) context[i] = global[i];
350
+ context.console = new Console(this.outputStream);
351
+ context.global = context;
352
+ context.global.global = context;
353
+ }
354
+
355
+ context.module = module;
356
+ context.require = require;
357
+
358
+ this.lines = [];
359
+ this.lines.level = [];
360
+
361
+ // make built-in modules available directly
362
+ // (loaded lazily)
363
+ exports._builtinLibs.forEach(function(name) {
364
+ Object.defineProperty(context, name, {
365
+ get: function() {
366
+ var lib = require(name);
367
+ context._ = context[name] = lib;
368
+ return lib;
369
+ },
370
+ // allow the creation of other globals with this name
371
+ set: function(val) {
372
+ delete context[name];
373
+ context[name] = val;
374
+ },
375
+ configurable: true
376
+ });
377
+ });
378
+
379
+ return context;
380
+ };
381
+
382
+ REPLServer.prototype.resetContext = function() {
383
+ this.context = this.createContext();
384
+
385
+ // Allow REPL extensions to extend the new context
386
+ this.emit('reset', this.context);
387
+ };
388
+
389
+ REPLServer.prototype.displayPrompt = function(preserveCursor) {
390
+ var prompt = this.prompt;
391
+ if (this.bufferedCommand.length) {
392
+ prompt = '...';
393
+ var levelInd = new Array(this.lines.level.length).join('..');
394
+ prompt += levelInd + ' ';
395
+ }
396
+ this.rli.setPrompt(prompt);
397
+ this.rli.prompt(preserveCursor);
398
+ };
399
+
400
+
401
+ // A stream to push an array into a REPL
402
+ // used in REPLServer.complete
403
+ function ArrayStream() {
404
+ Stream.call(this);
405
+
406
+ this.run = function(data) {
407
+ var self = this;
408
+ data.forEach(function(line) {
409
+ self.emit('data', line + '\n');
410
+ });
411
+ }
412
+ }
413
+ util.inherits(ArrayStream, Stream);
414
+ ArrayStream.prototype.readable = true;
415
+ ArrayStream.prototype.writable = true;
416
+ ArrayStream.prototype.resume = function() {};
417
+ ArrayStream.prototype.write = function() {};
418
+
419
+ var requireRE = /\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/;
420
+ var simpleExpressionRE =
421
+ /(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/;
422
+
423
+
424
+ // Provide a list of completions for the given leading text. This is
425
+ // given to the readline interface for handling tab completion.
426
+ //
427
+ // Example:
428
+ // complete('var foo = util.')
429
+ // -> [['util.print', 'util.debug', 'util.log', 'util.inspect', 'util.pump'],
430
+ // 'util.' ]
431
+ //
432
+ // Warning: This eval's code like "foo.bar.baz", so it will run property
433
+ // getter code.
434
+ REPLServer.prototype.complete = function(line, callback) {
435
+ // There may be local variables to evaluate, try a nested REPL
436
+ if (!util.isUndefined(this.bufferedCommand) && this.bufferedCommand.length) {
437
+ // Get a new array of inputed lines
438
+ var tmp = this.lines.slice();
439
+ // Kill off all function declarations to push all local variables into
440
+ // global scope
441
+ this.lines.level.forEach(function(kill) {
442
+ if (kill.isFunction) {
443
+ tmp[kill.line] = '';
444
+ }
445
+ });
446
+ var flat = new ArrayStream(); // make a new "input" stream
447
+ var magic = new REPLServer('', flat); // make a nested REPL
448
+ magic.context = magic.createContext();
449
+ flat.run(tmp); // eval the flattened code
450
+ // all this is only profitable if the nested REPL
451
+ // does not have a bufferedCommand
452
+ if (!magic.bufferedCommand) {
453
+ return magic.complete(line, callback);
454
+ }
455
+ }
456
+
457
+ var completions;
458
+
459
+ // list of completion lists, one for each inheritance "level"
460
+ var completionGroups = [];
461
+
462
+ var completeOn, match, filter, i, group, c;
463
+
464
+ // REPL commands (e.g. ".break").
465
+ var match = null;
466
+ match = line.match(/^\s*(\.\w*)$/);
467
+ if (match) {
468
+ completionGroups.push(Object.keys(this.commands));
469
+ completeOn = match[1];
470
+ if (match[1].length > 1) {
471
+ filter = match[1];
472
+ }
473
+
474
+ completionGroupsLoaded();
475
+ } else if (match = line.match(requireRE)) {
476
+ // require('...<Tab>')
477
+ var exts = Object.keys(require.extensions);
478
+ var indexRe = new RegExp('^index(' + exts.map(regexpEscape).join('|') +
479
+ ')$');
480
+
481
+ completeOn = match[1];
482
+ var subdir = match[2] || '';
483
+ var filter = match[1];
484
+ var dir, files, f, name, base, ext, abs, subfiles, s;
485
+ group = [];
486
+ var paths = module.paths.concat(require('module').globalPaths);
487
+ for (i = 0; i < paths.length; i++) {
488
+ dir = path.resolve(paths[i], subdir);
489
+ try {
490
+ files = fs.readdirSync(dir);
491
+ } catch (e) {
492
+ continue;
493
+ }
494
+ for (f = 0; f < files.length; f++) {
495
+ name = files[f];
496
+ ext = path.extname(name);
497
+ base = name.slice(0, -ext.length);
498
+ if (base.match(/-\d+\.\d+(\.\d+)?/) || name === '.npm') {
499
+ // Exclude versioned names that 'npm' installs.
500
+ continue;
501
+ }
502
+ if (exts.indexOf(ext) !== -1) {
503
+ if (!subdir || base !== 'index') {
504
+ group.push(subdir + base);
505
+ }
506
+ } else {
507
+ abs = path.resolve(dir, name);
508
+ try {
509
+ if (fs.statSync(abs).isDirectory()) {
510
+ group.push(subdir + name + '/');
511
+ subfiles = fs.readdirSync(abs);
512
+ for (s = 0; s < subfiles.length; s++) {
513
+ if (indexRe.test(subfiles[s])) {
514
+ group.push(subdir + name);
515
+ }
516
+ }
517
+ }
518
+ } catch (e) {}
519
+ }
520
+ }
521
+ }
522
+ if (group.length) {
523
+ completionGroups.push(group);
524
+ }
525
+
526
+ if (!subdir) {
527
+ completionGroups.push(exports._builtinLibs);
528
+ }
529
+
530
+ completionGroupsLoaded();
531
+
532
+ // Handle variable member lookup.
533
+ // We support simple chained expressions like the following (no function
534
+ // calls, etc.). That is for simplicity and also because we *eval* that
535
+ // leading expression so for safety (see WARNING above) don't want to
536
+ // eval function calls.
537
+ //
538
+ // foo.bar<|> # completions for 'foo' with filter 'bar'
539
+ // spam.eggs.<|> # completions for 'spam.eggs' with filter ''
540
+ // foo<|> # all scope vars with filter 'foo'
541
+ // foo.<|> # completions for 'foo' with filter ''
542
+ } else if (line.length === 0 || line[line.length - 1].match(/\w|\.|\$/)) {
543
+ match = simpleExpressionRE.exec(line);
544
+ if (line.length === 0 || match) {
545
+ var expr;
546
+ completeOn = (match ? match[0] : '');
547
+ if (line.length === 0) {
548
+ filter = '';
549
+ expr = '';
550
+ } else if (line[line.length - 1] === '.') {
551
+ filter = '';
552
+ expr = match[0].slice(0, match[0].length - 1);
553
+ } else {
554
+ var bits = match[0].split('.');
555
+ filter = bits.pop();
556
+ expr = bits.join('.');
557
+ }
558
+
559
+ // Resolve expr and get its completions.
560
+ var obj, memberGroups = [];
561
+ if (!expr) {
562
+ // If context is instance of vm.ScriptContext
563
+ // Get global vars synchronously
564
+ if (this.useGlobal ||
565
+ this.context.constructor &&
566
+ this.context.constructor.name === 'Context') {
567
+ var contextProto = this.context;
568
+ while (contextProto = Object.getPrototypeOf(contextProto)) {
569
+ completionGroups.push(Object.getOwnPropertyNames(contextProto));
570
+ }
571
+ completionGroups.push(Object.getOwnPropertyNames(this.context));
572
+ addStandardGlobals(completionGroups, filter);
573
+ completionGroupsLoaded();
574
+ } else {
575
+ this.eval('.scope', this.context, 'repl', function(err, globals) {
576
+ if (err || !globals) {
577
+ addStandardGlobals(completionGroups, filter);
578
+ } else if (util.isArray(globals[0])) {
579
+ // Add grouped globals
580
+ globals.forEach(function(group) {
581
+ completionGroups.push(group);
582
+ });
583
+ } else {
584
+ completionGroups.push(globals);
585
+ addStandardGlobals(completionGroups, filter);
586
+ }
587
+ completionGroupsLoaded();
588
+ });
589
+ }
590
+ } else {
591
+ this.eval(expr, this.context, 'repl', function(e, obj) {
592
+ // if (e) console.log(e);
593
+
594
+ if (obj != null) {
595
+ if (util.isObject(obj) || util.isFunction(obj)) {
596
+ memberGroups.push(Object.getOwnPropertyNames(obj));
597
+ }
598
+ // works for non-objects
599
+ try {
600
+ var sentinel = 5;
601
+ var p;
602
+ if (util.isObject(obj) || util.isFunction(obj)) {
603
+ p = Object.getPrototypeOf(obj);
604
+ } else {
605
+ p = obj.constructor ? obj.constructor.prototype : null;
606
+ }
607
+ while (!util.isNull(p)) {
608
+ memberGroups.push(Object.getOwnPropertyNames(p));
609
+ p = Object.getPrototypeOf(p);
610
+ // Circular refs possible? Let's guard against that.
611
+ sentinel--;
612
+ if (sentinel <= 0) {
613
+ break;
614
+ }
615
+ }
616
+ } catch (e) {
617
+ //console.log("completion error walking prototype chain:" + e);
618
+ }
619
+ }
620
+
621
+ if (memberGroups.length) {
622
+ for (i = 0; i < memberGroups.length; i++) {
623
+ completionGroups.push(memberGroups[i].map(function(member) {
624
+ return expr + '.' + member;
625
+ }));
626
+ }
627
+ if (filter) {
628
+ filter = expr + '.' + filter;
629
+ }
630
+ }
631
+
632
+ completionGroupsLoaded();
633
+ });
634
+ }
635
+ } else {
636
+ completionGroupsLoaded();
637
+ }
638
+ } else {
639
+ completionGroupsLoaded();
640
+ }
641
+
642
+ // Will be called when all completionGroups are in place
643
+ // Useful for async autocompletion
644
+ function completionGroupsLoaded(err) {
645
+ if (err) throw err;
646
+
647
+ // Filter, sort (within each group), uniq and merge the completion groups.
648
+ if (completionGroups.length && filter) {
649
+ var newCompletionGroups = [];
650
+ for (i = 0; i < completionGroups.length; i++) {
651
+ group = completionGroups[i].filter(function(elem) {
652
+ return elem.indexOf(filter) == 0;
653
+ });
654
+ if (group.length) {
655
+ newCompletionGroups.push(group);
656
+ }
657
+ }
658
+ completionGroups = newCompletionGroups;
659
+ }
660
+
661
+ if (completionGroups.length) {
662
+ var uniq = {}; // unique completions across all groups
663
+ completions = [];
664
+ // Completion group 0 is the "closest"
665
+ // (least far up the inheritance chain)
666
+ // so we put its completions last: to be closest in the REPL.
667
+ for (i = completionGroups.length - 1; i >= 0; i--) {
668
+ group = completionGroups[i];
669
+ group.sort();
670
+ for (var j = 0; j < group.length; j++) {
671
+ c = group[j];
672
+ if (!hasOwnProperty(uniq, c)) {
673
+ completions.push(c);
674
+ uniq[c] = true;
675
+ }
676
+ }
677
+ completions.push(''); // separator btwn groups
678
+ }
679
+ while (completions.length && completions[completions.length - 1] === '') {
680
+ completions.pop();
681
+ }
682
+ }
683
+
684
+ callback(null, [completions || [], completeOn]);
685
+ }
686
+ };
687
+
688
+
689
+ /**
690
+ * Used to parse and execute the Node REPL commands.
691
+ *
692
+ * @param {keyword} keyword The command entered to check.
693
+ * @return {Boolean} If true it means don't continue parsing the command.
694
+ */
695
+ REPLServer.prototype.parseREPLKeyword = function(keyword, rest) {
696
+ var cmd = this.commands[keyword];
697
+ if (cmd) {
698
+ cmd.action.call(this, rest);
699
+ return true;
700
+ }
701
+ return false;
702
+ };
703
+
704
+
705
+ REPLServer.prototype.defineCommand = function(keyword, cmd) {
706
+ if (util.isFunction(cmd)) {
707
+ cmd = {action: cmd};
708
+ } else if (!util.isFunction(cmd.action)) {
709
+ throw new Error('bad argument, action must be a function');
710
+ }
711
+ this.commands['.' + keyword] = cmd;
712
+ };
713
+
714
+ REPLServer.prototype.memory = function memory(cmd) {
715
+ var self = this;
716
+
717
+ self.lines = self.lines || [];
718
+ self.lines.level = self.lines.level || [];
719
+
720
+ // save the line so I can do magic later
721
+ if (cmd) {
722
+ // TODO should I tab the level?
723
+ self.lines.push(new Array(self.lines.level.length).join(' ') + cmd);
724
+ } else {
725
+ // I don't want to not change the format too much...
726
+ self.lines.push('');
727
+ }
728
+
729
+ // I need to know "depth."
730
+ // Because I can not tell the difference between a } that
731
+ // closes an object literal and a } that closes a function
732
+ if (cmd) {
733
+ // going down is { and ( e.g. function() {
734
+ // going up is } and )
735
+ var dw = cmd.match(/{|\(/g);
736
+ var up = cmd.match(/}|\)/g);
737
+ up = up ? up.length : 0;
738
+ dw = dw ? dw.length : 0;
739
+ var depth = dw - up;
740
+
741
+ if (depth) {
742
+ (function workIt() {
743
+ if (depth > 0) {
744
+ // going... down.
745
+ // push the line#, depth count, and if the line is a function.
746
+ // Since JS only has functional scope I only need to remove
747
+ // "function() {" lines, clearly this will not work for
748
+ // "function()
749
+ // {" but nothing should break, only tab completion for local
750
+ // scope will not work for this function.
751
+ self.lines.level.push({
752
+ line: self.lines.length - 1,
753
+ depth: depth,
754
+ isFunction: /\s*function\s*/.test(cmd)
755
+ });
756
+ } else if (depth < 0) {
757
+ // going... up.
758
+ var curr = self.lines.level.pop();
759
+ if (curr) {
760
+ var tmp = curr.depth + depth;
761
+ if (tmp < 0) {
762
+ //more to go, recurse
763
+ depth += curr.depth;
764
+ workIt();
765
+ } else if (tmp > 0) {
766
+ //remove and push back
767
+ curr.depth += depth;
768
+ self.lines.level.push(curr);
769
+ }
770
+ }
771
+ }
772
+ }());
773
+ }
774
+
775
+ // it is possible to determine a syntax error at this point.
776
+ // if the REPL still has a bufferedCommand and
777
+ // self.lines.level.length === 0
778
+ // TODO? keep a log of level so that any syntax breaking lines can
779
+ // be cleared on .break and in the case of a syntax error?
780
+ // TODO? if a log was kept, then I could clear the bufferedComand and
781
+ // eval these lines and throw the syntax error
782
+ } else {
783
+ self.lines.level = [];
784
+ }
785
+ };
786
+
787
+ function addStandardGlobals(completionGroups, filter) {
788
+ // Global object properties
789
+ // (http://www.ecma-international.org/publications/standards/Ecma-262.htm)
790
+ completionGroups.push(['NaN', 'Infinity', 'undefined',
791
+ 'eval', 'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'decodeURI',
792
+ 'decodeURIComponent', 'encodeURI', 'encodeURIComponent',
793
+ 'Object', 'Function', 'Array', 'String', 'Boolean', 'Number',
794
+ 'Date', 'RegExp', 'Error', 'EvalError', 'RangeError',
795
+ 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError',
796
+ 'Math', 'JSON']);
797
+ // Common keywords. Exclude for completion on the empty string, b/c
798
+ // they just get in the way.
799
+ if (filter) {
800
+ completionGroups.push(['break', 'case', 'catch', 'const',
801
+ 'continue', 'debugger', 'default', 'delete', 'do', 'else',
802
+ 'export', 'false', 'finally', 'for', 'function', 'if',
803
+ 'import', 'in', 'instanceof', 'let', 'new', 'null', 'return',
804
+ 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'undefined',
805
+ 'var', 'void', 'while', 'with', 'yield']);
806
+ }
807
+ }
808
+
809
+ function defineDefaultCommands(repl) {
810
+ // TODO remove me after 0.3.x
811
+ repl.defineCommand('break', {
812
+ help: 'Sometimes you get stuck, this gets you out',
813
+ action: function() {
814
+ this.bufferedCommand = '';
815
+ this.displayPrompt();
816
+ }
817
+ });
818
+
819
+ var clearMessage;
820
+ if (repl.useGlobal) {
821
+ clearMessage = 'Alias for .break';
822
+ } else {
823
+ clearMessage = 'Break, and also clear the local context';
824
+ }
825
+ repl.defineCommand('clear', {
826
+ help: clearMessage,
827
+ action: function() {
828
+ this.bufferedCommand = '';
829
+ if (!this.useGlobal) {
830
+ this.outputStream.write('Clearing context...\n');
831
+ this.resetContext();
832
+ }
833
+ this.displayPrompt();
834
+ }
835
+ });
836
+
837
+ repl.defineCommand('exit', {
838
+ help: 'Exit the repl',
839
+ action: function() {
840
+ this.rli.close();
841
+ }
842
+ });
843
+
844
+ repl.defineCommand('help', {
845
+ help: 'Show repl options',
846
+ action: function() {
847
+ var self = this;
848
+ Object.keys(this.commands).sort().forEach(function(name) {
849
+ var cmd = self.commands[name];
850
+ self.outputStream.write(name + '\t' + (cmd.help || '') + '\n');
851
+ });
852
+ this.displayPrompt();
853
+ }
854
+ });
855
+
856
+ repl.defineCommand('save', {
857
+ help: 'Save all evaluated commands in this REPL session to a file',
858
+ action: function(file) {
859
+ try {
860
+ fs.writeFileSync(file, this.lines.join('\n') + '\n');
861
+ this.outputStream.write('Session saved to:' + file + '\n');
862
+ } catch (e) {
863
+ this.outputStream.write('Failed to save:' + file + '\n');
864
+ }
865
+ this.displayPrompt();
866
+ }
867
+ });
868
+
869
+ repl.defineCommand('load', {
870
+ help: 'Load JS from a file into the REPL session',
871
+ action: function(file) {
872
+ try {
873
+ var stats = fs.statSync(file);
874
+ if (stats && stats.isFile()) {
875
+ var self = this;
876
+ var data = fs.readFileSync(file, 'utf8');
877
+ var lines = data.split('\n');
878
+ this.displayPrompt();
879
+ lines.forEach(function(line) {
880
+ if (line) {
881
+ self.rli.write(line + '\n');
882
+ }
883
+ });
884
+ }
885
+ } catch (e) {
886
+ this.outputStream.write('Failed to load:' + file + '\n');
887
+ }
888
+ this.displayPrompt();
889
+ }
890
+ });
891
+ }
892
+
893
+
894
+ function trimWhitespace(cmd) {
895
+ var trimmer = /^\s*(.+)\s*$/m,
896
+ matches = trimmer.exec(cmd);
897
+
898
+ if (matches && matches.length === 2) {
899
+ return matches[1];
900
+ }
901
+ return '';
902
+ }
903
+
904
+
905
+ function regexpEscape(s) {
906
+ return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
907
+ }
908
+
909
+
910
+ /**
911
+ * Converts commands that use var and function <name>() to use the
912
+ * local exports.context when evaled. This provides a local context
913
+ * on the REPL.
914
+ *
915
+ * @param {String} cmd The cmd to convert.
916
+ * @return {String} The converted command.
917
+ */
918
+ REPLServer.prototype.convertToContext = function(cmd) {
919
+ var self = this, matches,
920
+ scopeVar = /^\s*var\s*([_\w\$]+)(.*)$/m,
921
+ scopeFunc = /^\s*function\s*([_\w\$]+)/;
922
+
923
+ // Replaces: var foo = "bar"; with: self.context.foo = bar;
924
+ matches = scopeVar.exec(cmd);
925
+ if (matches && matches.length === 3) {
926
+ return 'self.context.' + matches[1] + matches[2];
927
+ }
928
+
929
+ // Replaces: function foo() {}; with: foo = function foo() {};
930
+ matches = scopeFunc.exec(self.bufferedCommand);
931
+ if (matches && matches.length === 2) {
932
+ return matches[1] + ' = ' + self.bufferedCommand;
933
+ }
934
+
935
+ return cmd;
936
+ };
937
+
938
+
939
+ // If the error is that we've unexpectedly ended the input,
940
+ // then let the user try to recover by adding more input.
941
+ function isRecoverableError(e) {
942
+ return e &&
943
+ e.name === 'SyntaxError' &&
944
+ /^Unexpected end of input/.test(e.message);
945
+ }