macgyver 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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
+ }