@@ -1047,7 +1047,7 @@ REPLServer.prototype.turnOffEditorMode = deprecate(
1047
1047
'REPLServer.turnOffEditorMode() is deprecated' ,
1048
1048
'DEP0078' ) ;
1049
1049
1050
- const requireRE = / \b r e q u i r e \s * \( [ ' " ] ( ( [ \w @ . / - ] + \/ ) ? (?: [ \w @ . / - ] * ) ) / ;
1050
+ const requireRE = / \b r e q u i r e \s * \( \s * [ ' " ` ] ( ( [ \w @ . / - ] + \/ ) ? (?: [ \w @ . / - ] * ) ) (? ! [ ^ ' " ` ] ) $ / ;
1051
1051
const fsAutoCompleteRE = / f s (?: \. p r o m i s e s ) ? \. \s * [ a - z ] [ a - z A - Z ] + \( \s * [ " ' ] ( .* ) / ;
1052
1052
const simpleExpressionRE =
1053
1053
/ (?: [ a - z A - Z _ $ ] (?: \w | \$ ) * \. ) * [ a - z A - Z _ $ ] (?: \w | \$ ) * \. ? $ / ;
@@ -1095,8 +1095,13 @@ REPLServer.prototype.complete = function() {
1095
1095
this . completer . apply ( this , arguments ) ;
1096
1096
} ;
1097
1097
1098
- // TODO: Native module names should be auto-resolved.
1099
- // That improves the auto completion.
1098
+ function gracefulOperation ( fn , args , alternative ) {
1099
+ try {
1100
+ return fn ( ...args ) ;
1101
+ } catch {
1102
+ return alternative ;
1103
+ }
1104
+ }
1100
1105
1101
1106
// Provide a list of completions for the given leading text. This is
1102
1107
// given to the readline interface for handling tab completion.
@@ -1118,26 +1123,25 @@ function complete(line, callback) {
1118
1123
1119
1124
// REPL commands (e.g. ".break").
1120
1125
let filter ;
1121
- let match = line . match ( / ^ \s * \. ( \w * ) $ / ) ;
1122
- if ( match ) {
1126
+ if ( / ^ \s * \. ( \w * ) $ / . test ( line ) ) {
1123
1127
completionGroups . push ( ObjectKeys ( this . commands ) ) ;
1124
- completeOn = match [ 1 ] ;
1125
- if ( match [ 1 ] . length ) {
1126
- filter = match [ 1 ] ;
1128
+ completeOn = line . match ( / ^ \s * \. ( \w * ) $ / ) [ 1 ] ;
1129
+ if ( completeOn . length ) {
1130
+ filter = completeOn ;
1127
1131
}
1128
1132
1129
1133
completionGroupsLoaded ( ) ;
1130
- } else if ( match = line . match ( requireRE ) ) {
1134
+ } else if ( requireRE . test ( line ) ) {
1131
1135
// require('...<Tab>')
1132
- const exts = ObjectKeys ( this . context . require . extensions ) ;
1133
- const indexRe = new RegExp ( '^index(?:' + exts . map ( regexpEscape ) . join ( '|' ) +
1134
- ')$ ') ;
1136
+ const extensions = ObjectKeys ( this . context . require . extensions ) ;
1137
+ const indexes = extensions . map ( ( extension ) => `index ${ extension } ` ) ;
1138
+ indexes . push ( 'package.json' , 'index ') ;
1135
1139
const versionedFileNamesRe = / - \d + \. \d + / ;
1136
1140
1141
+ const match = line . match ( requireRE ) ;
1137
1142
completeOn = match [ 1 ] ;
1138
1143
const subdir = match [ 2 ] || '' ;
1139
- filter = match [ 1 ] ;
1140
- let dir , files , subfiles , isDirectory ;
1144
+ filter = completeOn ;
1141
1145
group = [ ] ;
1142
1146
let paths = [ ] ;
1143
1147
@@ -1151,41 +1155,31 @@ function complete(line, callback) {
1151
1155
paths = module . paths . concat ( CJSModule . globalPaths ) ;
1152
1156
}
1153
1157
1154
- for ( let i = 0 ; i < paths . length ; i ++ ) {
1155
- dir = path . resolve ( paths [ i ] , subdir ) ;
1156
- try {
1157
- files = fs . readdirSync ( dir ) ;
1158
- } catch {
1159
- continue ;
1160
- }
1161
- for ( let f = 0 ; f < files . length ; f ++ ) {
1162
- const name = files [ f ] ;
1158
+ for ( let dir of paths ) {
1159
+ dir = path . resolve ( dir , subdir ) ;
1160
+ const files = gracefulOperation ( fs . readdirSync , [ dir ] , [ ] ) ;
1161
+ for ( const name of files ) {
1163
1162
const ext = path . extname ( name ) ;
1164
1163
const base = name . slice ( 0 , - ext . length ) ;
1165
1164
if ( versionedFileNamesRe . test ( base ) || name === '.npm' ) {
1166
1165
// Exclude versioned names that 'npm' installs.
1167
1166
continue ;
1168
1167
}
1169
1168
const abs = path . resolve ( dir , name ) ;
1170
- try {
1171
- isDirectory = fs . statSync ( abs ) . isDirectory ( ) ;
1172
- } catch {
1169
+ const stats = gracefulOperation ( fs . statSync , [ abs ] ) ;
1170
+ if ( ! stats || ! stats . isDirectory ( ) ) {
1171
+ if ( extensions . includes ( ext ) && ( ! subdir || base !== 'index' ) ) {
1172
+ group . push ( `${ subdir } ${ base } ` ) ;
1173
+ }
1173
1174
continue ;
1174
1175
}
1175
- if ( isDirectory ) {
1176
- group . push ( subdir + name + '/' ) ;
1177
- try {
1178
- subfiles = fs . readdirSync ( abs ) ;
1179
- } catch {
1180
- continue ;
1181
- }
1182
- for ( let s = 0 ; s < subfiles . length ; s ++ ) {
1183
- if ( indexRe . test ( subfiles [ s ] ) ) {
1184
- group . push ( subdir + name ) ;
1185
- }
1176
+ group . push ( `${ subdir } ${ name } /` ) ;
1177
+ const subfiles = gracefulOperation ( fs . readdirSync , [ abs ] , [ ] ) ;
1178
+ for ( const subfile of subfiles ) {
1179
+ if ( indexes . includes ( subfile ) ) {
1180
+ group . push ( `${ subdir } ${ name } ` ) ;
1181
+ break ;
1186
1182
}
1187
- } else if ( exts . includes ( ext ) && ( ! subdir || base !== 'index' ) ) {
1188
- group . push ( subdir + base ) ;
1189
1183
}
1190
1184
}
1191
1185
}
@@ -1198,11 +1192,10 @@ function complete(line, callback) {
1198
1192
}
1199
1193
1200
1194
completionGroupsLoaded ( ) ;
1201
- } else if ( match = line . match ( fsAutoCompleteRE ) ) {
1202
-
1203
- let filePath = match [ 1 ] ;
1204
- let fileList ;
1195
+ } else if ( fsAutoCompleteRE . test ( line ) ) {
1205
1196
filter = '' ;
1197
+ let filePath = line . match ( fsAutoCompleteRE ) [ 1 ] ;
1198
+ let fileList ;
1206
1199
1207
1200
try {
1208
1201
fileList = fs . readdirSync ( filePath , { withFileTypes : true } ) ;
@@ -1233,7 +1226,7 @@ function complete(line, callback) {
1233
1226
// foo<|> # all scope vars with filter 'foo'
1234
1227
// foo.<|> # completions for 'foo' with filter ''
1235
1228
} else if ( line . length === 0 || / \w | \. | \$ / . test ( line [ line . length - 1 ] ) ) {
1236
- match = simpleExpressionRE . exec ( line ) ;
1229
+ const match = simpleExpressionRE . exec ( line ) ;
1237
1230
if ( line . length !== 0 && ! match ) {
1238
1231
completionGroupsLoaded ( ) ;
1239
1232
return ;
@@ -1583,10 +1576,6 @@ function defineDefaultCommands(repl) {
1583
1576
}
1584
1577
}
1585
1578
1586
- function regexpEscape ( s ) {
1587
- return s . replace ( / [ - [ \] { } ( ) * + ? . , \\ ^ $ | # \s ] / g, '\\$&' ) ;
1588
- }
1589
-
1590
1579
function Recoverable ( err ) {
1591
1580
this . err = err ;
1592
1581
}
0 commit comments