Skip to content

Commit 1555dbd

Browse files
Mesteerytargos
authored andcommitted
repl: fix and extend require/import tab complete
PR-URL: #40216 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 0201f3f commit 1555dbd

File tree

3 files changed

+108
-114
lines changed

3 files changed

+108
-114
lines changed

lib/repl.js

+106-108
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}`);
@@ -1287,135 +1287,133 @@ function complete(line, callback) {
12871287
if (completeOn.length) {
12881288
filter = completeOn;
12891289
}
1290-
} else if (RegExpPrototypeTest(requireRE, line) &&
1291-
this.allowBlockingCompletions) {
1290+
} else if (RegExpPrototypeTest(requireRE, line)) {
12921291
// require('...<Tab>')
1293-
const extensions = ObjectKeys(this.context.require.extensions);
1294-
const indexes = ArrayPrototypeMap(extensions,
1295-
(extension) => `index${extension}`);
1296-
ArrayPrototypePush(indexes, 'package.json', 'index');
1297-
12981292
const match = StringPrototypeMatch(line, requireRE);
12991293
completeOn = match[1];
1300-
const subdir = match[2] || '';
13011294
filter = completeOn;
1302-
group = [];
1303-
let paths = [];
1304-
1305-
if (completeOn === '.') {
1306-
group = ['./', '../'];
1307-
} else if (completeOn === '..') {
1308-
group = ['../'];
1309-
} else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) {
1310-
paths = [process.cwd()];
1311-
} else {
1312-
paths = ArrayPrototypeConcat(module.paths, CJSModule.globalPaths);
1313-
}
1295+
if (this.allowBlockingCompletions) {
1296+
const subdir = match[2] || '';
1297+
const extensions = ObjectKeys(this.context.require.extensions);
1298+
const indexes = ArrayPrototypeMap(extensions,
1299+
(extension) => `index${extension}`);
1300+
ArrayPrototypePush(indexes, 'package.json', 'index');
1301+
1302+
group = [];
1303+
let paths = [];
1304+
1305+
if (completeOn === '.') {
1306+
group = ['./', '../'];
1307+
} else if (completeOn === '..') {
1308+
group = ['../'];
1309+
} else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) {
1310+
paths = [process.cwd()];
1311+
} else {
1312+
paths = ArrayPrototypeConcat(module.paths, CJSModule.globalPaths);
1313+
}
13141314

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

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

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

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

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

1412-
if (group.length) {
1413-
ArrayPrototypePush(completionGroups, group);
1411+
if (group.length) {
1412+
ArrayPrototypePush(completionGroups, group);
1413+
}
14141414
}
14151415

1416-
if (!subdir) {
1417-
ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs);
1418-
}
1416+
ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs);
14191417
} else if (RegExpPrototypeTest(fsAutoCompleteRE, line) &&
14201418
this.allowBlockingCompletions) {
14211419
({ 0: completionGroups, 1: completeOn } = completeFSFunctions(line));

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

+1-3
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

+1-3
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)