Skip to content

Commit 9100646

Browse files
committed
repl: fix and extend require/import tab complete
1 parent fd86dad commit 9100646

File tree

3 files changed

+108
-114
lines changed

3 files changed

+108
-114
lines changed

lib/repl.js

Lines changed: 106 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ const { Console } = require('console');
125125
const CJSModule = require('internal/modules/cjs/loader').Module;
126126
let _builtinLibs = ArrayPrototypeFilter(
127127
CJSModule.builtinModules,
128-
(e) => !StringPrototypeStartsWith(e, '_') && !StringPrototypeIncludes(e, '/')
128+
(e) => !StringPrototypeStartsWith(e, '_'),
129129
);
130130
const nodeSchemeBuiltinLibs = ArrayPrototypeMap(
131131
_builtinLibs, (lib) => `node:${lib}`);
@@ -1285,135 +1285,133 @@ function complete(line, callback) {
12851285
if (completeOn.length) {
12861286
filter = completeOn;
12871287
}
1288-
} else if (RegExpPrototypeTest(requireRE, line) &&
1289-
this.allowBlockingCompletions) {
1288+
} else if (RegExpPrototypeTest(requireRE, line)) {
12901289
// require('...<Tab>')
1291-
const extensions = ObjectKeys(this.context.require.extensions);
1292-
const indexes = ArrayPrototypeMap(extensions,
1293-
(extension) => `index${extension}`);
1294-
ArrayPrototypePush(indexes, 'package.json', 'index');
1295-
12961290
const match = StringPrototypeMatch(line, requireRE);
12971291
completeOn = match[1];
1298-
const subdir = match[2] || '';
12991292
filter = completeOn;
1300-
group = [];
1301-
let paths = [];
1302-
1303-
if (completeOn === '.') {
1304-
group = ['./', '../'];
1305-
} else if (completeOn === '..') {
1306-
group = ['../'];
1307-
} else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) {
1308-
paths = [process.cwd()];
1309-
} else {
1310-
paths = ArrayPrototypeConcat(module.paths, CJSModule.globalPaths);
1311-
}
1293+
if (this.allowBlockingCompletions) {
1294+
const subdir = match[2] || '';
1295+
const extensions = ObjectKeys(this.context.require.extensions);
1296+
const indexes = ArrayPrototypeMap(extensions,
1297+
(extension) => `index${extension}`);
1298+
ArrayPrototypePush(indexes, 'package.json', 'index');
1299+
1300+
group = [];
1301+
let paths = [];
1302+
1303+
if (completeOn === '.') {
1304+
group = ['./', '../'];
1305+
} else if (completeOn === '..') {
1306+
group = ['../'];
1307+
} else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) {
1308+
paths = [process.cwd()];
1309+
} else {
1310+
paths = ArrayPrototypeConcat(module.paths, CJSModule.globalPaths);
1311+
}
13121312

1313-
ArrayPrototypeForEach(paths, (dir) => {
1314-
dir = path.resolve(dir, subdir);
1315-
const dirents = gracefulReaddir(dir, { withFileTypes: true }) || [];
1316-
ArrayPrototypeForEach(dirents, (dirent) => {
1317-
if (RegExpPrototypeTest(versionedFileNamesRe, dirent.name) ||
1318-
dirent.name === '.npm') {
1319-
// Exclude versioned names that 'npm' installs.
1320-
return;
1321-
}
1322-
const extension = path.extname(dirent.name);
1323-
const base = StringPrototypeSlice(dirent.name, 0, -extension.length);
1324-
if (!dirent.isDirectory()) {
1325-
if (StringPrototypeIncludes(extensions, extension) &&
1326-
(!subdir || base !== 'index')) {
1327-
ArrayPrototypePush(group, `${subdir}${base}`);
1313+
ArrayPrototypeForEach(paths, (dir) => {
1314+
dir = path.resolve(dir, subdir);
1315+
const dirents = gracefulReaddir(dir, { withFileTypes: true }) || [];
1316+
ArrayPrototypeForEach(dirents, (dirent) => {
1317+
if (RegExpPrototypeTest(versionedFileNamesRe, dirent.name) ||
1318+
dirent.name === '.npm') {
1319+
// Exclude versioned names that 'npm' installs.
1320+
return;
13281321
}
1329-
return;
1330-
}
1331-
ArrayPrototypePush(group, `${subdir}${dirent.name}/`);
1332-
const absolute = path.resolve(dir, dirent.name);
1333-
if (ArrayPrototypeSome(
1334-
gracefulReaddir(absolute) || [],
1335-
(subfile) => ArrayPrototypeIncludes(indexes, subfile)
1336-
)) {
1337-
ArrayPrototypePush(group, `${subdir}${dirent.name}`);
1338-
}
1322+
const extension = path.extname(dirent.name);
1323+
const base = StringPrototypeSlice(dirent.name, 0, -extension.length);
1324+
if (!dirent.isDirectory()) {
1325+
if (StringPrototypeIncludes(extensions, extension) &&
1326+
(!subdir || base !== 'index')) {
1327+
ArrayPrototypePush(group, `${subdir}${base}`);
1328+
}
1329+
return;
1330+
}
1331+
ArrayPrototypePush(group, `${subdir}${dirent.name}/`);
1332+
const absolute = path.resolve(dir, dirent.name);
1333+
if (ArrayPrototypeSome(
1334+
gracefulReaddir(absolute) || [],
1335+
(subfile) => ArrayPrototypeIncludes(indexes, subfile)
1336+
)) {
1337+
ArrayPrototypePush(group, `${subdir}${dirent.name}`);
1338+
}
1339+
});
13391340
});
1340-
});
1341-
if (group.length) {
1342-
ArrayPrototypePush(completionGroups, group);
1341+
if (group.length) {
1342+
ArrayPrototypePush(completionGroups, group);
1343+
}
13431344
}
13441345

1345-
if (!subdir) {
1346-
ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs);
1347-
}
1348-
} else if (RegExpPrototypeTest(importRE, line) &&
1349-
this.allowBlockingCompletions) {
1346+
ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs);
1347+
} else if (RegExpPrototypeTest(importRE, line)) {
13501348
// import('...<Tab>')
1351-
// File extensions that can be imported:
1352-
const extensions = ObjectKeys(
1353-
getOptionValue('--experimental-specifier-resolution') === 'node' ?
1354-
legacyExtensionFormatMap :
1355-
extensionFormatMap);
1356-
1357-
// Only used when loading bare module specifiers from `node_modules`:
1358-
const indexes = ArrayPrototypeMap(extensions, (ext) => `index${ext}`);
1359-
ArrayPrototypePush(indexes, 'package.json');
1360-
13611349
const match = StringPrototypeMatch(line, importRE);
13621350
completeOn = match[1];
1363-
const subdir = match[2] || '';
13641351
filter = completeOn;
1365-
group = [];
1366-
let paths = [];
1367-
if (completeOn === '.') {
1368-
group = ['./', '../'];
1369-
} else if (completeOn === '..') {
1370-
group = ['../'];
1371-
} else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) {
1372-
paths = [process.cwd()];
1373-
} else {
1374-
paths = ArrayPrototypeSlice(module.paths);
1375-
}
1352+
if (this.allowBlockingCompletions) {
1353+
const subdir = match[2] || '';
1354+
// File extensions that can be imported:
1355+
const extensions = ObjectKeys(
1356+
getOptionValue('--experimental-specifier-resolution') === 'node' ?
1357+
legacyExtensionFormatMap :
1358+
extensionFormatMap);
1359+
1360+
// Only used when loading bare module specifiers from `node_modules`:
1361+
const indexes = ArrayPrototypeMap(extensions, (ext) => `index${ext}`);
1362+
ArrayPrototypePush(indexes, 'package.json');
1363+
1364+
group = [];
1365+
let paths = [];
1366+
if (completeOn === '.') {
1367+
group = ['./', '../'];
1368+
} else if (completeOn === '..') {
1369+
group = ['../'];
1370+
} else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) {
1371+
paths = [process.cwd()];
1372+
} else {
1373+
paths = ArrayPrototypeSlice(module.paths);
1374+
}
13761375

1377-
ArrayPrototypeForEach(paths, (dir) => {
1378-
dir = path.resolve(dir, subdir);
1379-
const isInNodeModules = path.basename(dir) === 'node_modules';
1380-
const dirents = gracefulReaddir(dir, { withFileTypes: true }) || [];
1381-
ArrayPrototypeForEach(dirents, (dirent) => {
1382-
const { name } = dirent;
1383-
if (RegExpPrototypeTest(versionedFileNamesRe, name) ||
1384-
name === '.npm') {
1385-
// Exclude versioned names that 'npm' installs.
1386-
return;
1387-
}
1376+
ArrayPrototypeForEach(paths, (dir) => {
1377+
dir = path.resolve(dir, subdir);
1378+
const isInNodeModules = path.basename(dir) === 'node_modules';
1379+
const dirents = gracefulReaddir(dir, { withFileTypes: true }) || [];
1380+
ArrayPrototypeForEach(dirents, (dirent) => {
1381+
const { name } = dirent;
1382+
if (RegExpPrototypeTest(versionedFileNamesRe, name) ||
1383+
name === '.npm') {
1384+
// Exclude versioned names that 'npm' installs.
1385+
return;
1386+
}
13881387

1389-
if (!dirent.isDirectory()) {
1390-
const extension = path.extname(name);
1391-
if (StringPrototypeIncludes(extensions, extension)) {
1392-
ArrayPrototypePush(group, `${subdir}${name}`);
1388+
if (!dirent.isDirectory()) {
1389+
const extension = path.extname(name);
1390+
if (StringPrototypeIncludes(extensions, extension)) {
1391+
ArrayPrototypePush(group, `${subdir}${name}`);
1392+
}
1393+
return;
13931394
}
1394-
return;
1395-
}
13961395

1397-
ArrayPrototypePush(group, `${subdir}${name}/`);
1398-
if (!subdir && isInNodeModules) {
1399-
const absolute = path.resolve(dir, name);
1400-
const subfiles = gracefulReaddir(absolute) || [];
1401-
if (ArrayPrototypeSome(subfiles, (subfile) => {
1402-
return ArrayPrototypeIncludes(indexes, subfile);
1403-
})) {
1404-
ArrayPrototypePush(group, `${subdir}${name}`);
1396+
ArrayPrototypePush(group, `${subdir}${name}/`);
1397+
if (!subdir && isInNodeModules) {
1398+
const absolute = path.resolve(dir, name);
1399+
const subfiles = gracefulReaddir(absolute) || [];
1400+
if (ArrayPrototypeSome(subfiles, (subfile) => {
1401+
return ArrayPrototypeIncludes(indexes, subfile);
1402+
})) {
1403+
ArrayPrototypePush(group, `${subdir}${name}`);
1404+
}
14051405
}
1406-
}
1406+
});
14071407
});
1408-
});
14091408

1410-
if (group.length) {
1411-
ArrayPrototypePush(completionGroups, group);
1409+
if (group.length) {
1410+
ArrayPrototypePush(completionGroups, group);
1411+
}
14121412
}
14131413

1414-
if (!subdir) {
1415-
ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs);
1416-
}
1414+
ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs);
14171415
} else if (RegExpPrototypeTest(fsAutoCompleteRE, line) &&
14181416
this.allowBlockingCompletions) {
14191417
({ 0: completionGroups, 1: completeOn } = completeFSFunctions(line));

test/parallel/test-repl-tab-complete-import.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ const ArrayStream = require('../common/arraystream');
55
const fixtures = require('../common/fixtures');
66
const assert = require('assert');
77
const { builtinModules } = require('module');
8-
const publicModules = builtinModules.filter(
9-
(lib) => !lib.startsWith('_') && !lib.includes('/'),
10-
);
8+
const publicModules = builtinModules.filter((lib) => !lib.startsWith('_'));
119

1210
if (!common.isMainThread)
1311
common.skip('process.chdir is not available in Workers');

test/parallel/test-repl-tab-complete.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ const assert = require('assert');
3131
const path = require('path');
3232
const fixtures = require('../common/fixtures');
3333
const { builtinModules } = require('module');
34-
const publicModules = builtinModules.filter(
35-
(lib) => !lib.startsWith('_') && !lib.includes('/'),
36-
);
34+
const publicModules = builtinModules.filter((lib) => !lib.startsWith('_'));
3735

3836
const hasInspector = process.features.inspector;
3937

0 commit comments

Comments
 (0)