repl completion: completion for arguments to "require"
This commit is contained in:
parent
2134982ea4
commit
5c1ffa165f
73
lib/repl.js
73
lib/repl.js
@ -16,6 +16,7 @@ var sys = require('sys');
|
||||
var Script = process.binding('evals').Script;
|
||||
var evalcx = Script.runInContext;
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
var rl = require('readline');
|
||||
var context;
|
||||
|
||||
@ -162,7 +163,7 @@ REPLServer.prototype.complete = function (line) {
|
||||
completeOn,
|
||||
match, filter, i, j, group, c;
|
||||
|
||||
// REPL comments (e.g. ".break").
|
||||
// REPL commands (e.g. ".break").
|
||||
var match = null;
|
||||
match = line.match(/^\s*(\.\w*)$/);
|
||||
if (match) {
|
||||
@ -173,6 +174,72 @@ REPLServer.prototype.complete = function (line) {
|
||||
}
|
||||
}
|
||||
|
||||
// require('...<Tab>')
|
||||
else if (match = line.match(/\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/)) {
|
||||
//TODO: suggest require.exts be exposed to be introspec registered extensions?
|
||||
//TODO: suggest include the '.' in exts in internal repr: parity with `path.extname`.
|
||||
var exts = [".js", ".node"];
|
||||
var indexRe = new RegExp('^index(' + exts.map(regexpEscape).join('|') + ')$');
|
||||
|
||||
completeOn = match[1];
|
||||
var subdir = match[2] || "";
|
||||
var filter = match[1];
|
||||
var dir, files, f, name, base, ext, abs, subfiles, s;
|
||||
group = [];
|
||||
for (i = 0; i < require.paths.length; i++) {
|
||||
dir = require.paths[i];
|
||||
if (subdir && subdir[0] === '/') {
|
||||
dir = subdir;
|
||||
} else if (subdir) {
|
||||
dir = path.join(dir, subdir);
|
||||
}
|
||||
try {
|
||||
files = fs.readdirSync(dir);
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
for (f = 0; f < files.length; f++) {
|
||||
name = files[f];
|
||||
ext = path.extname(name);
|
||||
base = name.slice(0, -ext.length);
|
||||
if (base.match(/-\d+\.\d+(\.\d+)?/) || name === ".npm") {
|
||||
// Exclude versioned names that 'npm' installs.
|
||||
continue;
|
||||
}
|
||||
if (exts.indexOf(ext) !== -1) {
|
||||
if (!subdir || base !== "index") {
|
||||
group.push(subdir + base);
|
||||
}
|
||||
} else {
|
||||
abs = path.join(dir, name);
|
||||
try {
|
||||
if (fs.statSync(abs).isDirectory()) {
|
||||
group.push(subdir + name + '/');
|
||||
subfiles = fs.readdirSync(abs);
|
||||
for (s = 0; s < subfiles.length; s++) {
|
||||
if (indexRe.test(subfiles[s])) {
|
||||
group.push(subdir + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (group.length) {
|
||||
completionGroups.push(group);
|
||||
}
|
||||
|
||||
if (!subdir) {
|
||||
// Kind of lame that this needs to be updated manually.
|
||||
// Intentionally excluding moved modules: posix, utils.
|
||||
var builtinLibs = ['assert', 'buffer', 'child_process', 'crypto', 'dgram',
|
||||
'dns', 'events', 'file', 'freelist', 'fs', 'http', 'net', 'path',
|
||||
'querystring', 'readline', 'repl', 'string_decoder', 'sys', 'tcp', 'url'];
|
||||
completionGroups.push(builtinLibs);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle variable member lookup.
|
||||
// We support simple chained expressions like the following (no function
|
||||
// calls, etc.). That is for simplicity and also because we *eval* that
|
||||
@ -348,6 +415,10 @@ function trimWhitespace (cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
function regexpEscape(s) {
|
||||
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts commands that use var and function <name>() to use the
|
||||
* local exports.context when evaled. This provides a local context
|
||||
|
Loading…
x
Reference in New Issue
Block a user